Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
554 views
in Technique[技术] by (71.8m points)

c# - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...