15

I'm using PushFrame to ensure that my window finishes drawing before executing additional code. My application has some time sensitive functions that require the windows have been updated before I continues executing code.

So I'm using the sample from msdn: http://msdn.microsoft.com/en-us/library/vstudio/system.windows.threading.dispatcher.pushframe(v=vs.110).aspx

Which works great, except, if a user is dragging my window when this code executes the window hangs and you can only get it back with a ctrl-alt-del.

Any ideas?

6
  • sounds really awkward. Why don't you just Dispatcher.BeginInvoke() with the proper DispatcherPriority?
    – Fede
    Commented Oct 16, 2013 at 19:06
  • That is the ONLY way to guarantee that you've actually painted to the screen before you return. You do know begin invoke is asyncronous? If anything I'd want Invoke, but even with that you're still abstracted from the actual paint updates that the dispatcher handles in it's own time. Commented Oct 16, 2013 at 19:45
  • not really. using DispatcherPriority.ApplicationIdle guarantees that your code will be called after everything else has completed. BTW the word "painted" sounds too winforms. What are you actually trying to do?
    – Fede
    Commented Oct 16, 2013 at 19:47
  • 1
    Synchronize screen updates with physical hardware monitoring devices. Commented Oct 16, 2013 at 19:47
  • sounds to me you'd rather use the TPL and TaskScheduler.FromCurrentSynchronizationContext
    – Fede
    Commented Oct 16, 2013 at 19:49

2 Answers 2

6

The application seems freezed because mouse capture is not automatically released from the window resize or DragMove() operation after the Dispatcher.PushFrame() is called from the user code.

The workaround would be to manually release mouse capture from any window in the application that is capturing the mouse prior to calling Dispatcher.PushFrame():

        ...
        if (priority < DispatcherPriority.Loaded)
        {
            IntPtr capturingHandle = GetCapture();
            for (int i = 0; i < Application.Current.Windows.Count; i++)
            {
                if (new WindowInteropHelper(
                                            Application.Current.Windows[i]
                                           ).Handle == capturingHandle)
                {
                    Mouse.Capture(
                                  Application.Current.Windows[i],
                                  CaptureMode.Element
                                 );
                    Application.Current.Windows[i].ReleaseMouseCapture();
                    break;
                }
            }
        }
        ...

This workaround utilizes the GetCapture() p/invoke declaration:

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr GetCapture();
3

Unfortunately I do not have a solution for you but can only confirm we can reproduce this too in our application (and in a 50 line example program). Feel free to vote for this connect issue.

Not the answer you're looking for? Browse other questions tagged or ask your own question.