简体   繁体   中英

For what is PushFrame needed?

I came across with PushFrame method of Dispatcher object. It is simplified version of method:

public void PushFrame(DispatcherFrame frame)
{
    // Stuff
    _frameDepth++;

    while(frame.Continue)
    {
        // Getting and dispatching messages
    }

    _frameDepth--;
    // Stuff
}

In other words it just opens new message processing loop. But I really cannot understand benefits of such way. For what purposes is PushFrame used? Is there good examples of its usage? As for me, It seems like that this method will lead to not obvious errors.

It is essential plumbing for the dispatcher loop in a WPF program. Every GUI program on Windows has one, it is the universal solution to the producer-consumer problem . Where the OS and other programs produce and the UI thread of your WPF program consumes. A hard requirement for GUI apps, the library code that implements the GUI is never thread-safe. You can easily see the loop here, you cannot see the thread-safe queue that is emptied by the loop, it is built into the OS.

The loop is started by a call to Application.Run(). Not easy to see in a WPF app, it is auto-generated in most apps from your App.xaml file. That pushes the first "frame", your app keeps running as long as it stays inside the loop. You'll always see it back in the Call Stack debugger window when you set a breakpoint on an event handler. Closing the MainWindow of your app is the normal way the loop ends. Which in turn causes the Run() method to return, which terminates the UI thread, which terminates the process.

There are some scenarios where you like to have a nested dispatcher loop. A "modal loop". An example of such a modal loop that you use every day is when you click and drag the mouse on a window corner. All mouse and keyboard input now change the window size or location, they are no longer used to operate the UI in the normal way. Releasing the mouse terminates that loop. This dispatcher loop is built into the OS, it is not done by WPF.

But WPF has use for such a modal loop as well. The canonical example is the Window.ShowDialog() method. That method does not return until the dialog is closed. Achieved by WPF internally calling PushFrame() again. Just try it with the debugger, you'll see both PushFrame calls in the Call Stack window. The first one is the one that ShowDialog() called, the second one is the one that Application.Run() called. You'll get more if your dialog in turn displays a dialog.

A less obvious example is calling Dispatcher.Invoke() on the UI thread. A method that doesn't return until the invoked method returns. Normally a bit of a bug but there was no compelling reason to disallow it. A word of warning might be appropriate, modal loops are pretty dangerous. They have a knack for causing re-entrancy bugs . The kind of bug that made the DoEvents() method so notorious. A big reason why ShowDialog() disables all the other windows in your UI.

For what purposes is PushFrame used?

It is internally used to push frames onto the current dispatcher. How the dispatcher queue works in detail is quite a big topic but the following answer should be helpful.

Understanding the Dispatcher Queue

Is there good examples of its usage?

For example when you for some reason want to call an async method synchronously and continue to pump messages until the task completes. You will find a concrete sample implementation of this in Stephen Cleary's AsyncCTPUtil library on GitHub: https://github.com/StephenCleary/AsyncCTPUtil/blob/master/AsyncTestUtilities/WpfContext.cs

Please refer to his answer here for more information:

How would I run an async Task<T> method synchronously?

You could also refer to the following link: https://social.msdn.microsoft.com/Forums/vstudio/en-US/650e69f9-5f4d-4d77-8107-93fb6646f26d/solved-block-synchronous-method-while-waiting-for-async-method-to-complete?forum=wpf

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM