简体   繁体   English

什么是PushFrame需要?

[英]For what is PushFrame needed?

I came across with PushFrame method of Dispatcher object. 我遇到了Dispatcher对象的PushFrame方法。 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? PushFrame用于什么目的? 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. 它是WPF程序中调度程序循环的必要管道。 Every GUI program on Windows has one, it is the universal solution to the producer-consumer problem . Windows上的每个GUI程序都有一个,它是生产者 - 消费者问题的通用解决方案。 Where the OS and other programs produce and the UI thread of your WPF program consumes. 操作系统和其他程序生成的地方以及WPF程序的UI线程消耗。 A hard requirement for GUI apps, the library code that implements the GUI is never thread-safe. 对GUI应用程序的硬性要求,实现GUI的库代码从不是线程安全的。 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(). 通过调用Application.Run()启动循环。 Not easy to see in a WPF app, it is auto-generated in most apps from your App.xaml file. 在WPF应用程序中不容易看到,它是在App.xaml文件的大多数应用程序中自动生成的。 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. 关闭应用程序的MainWindow是循环结束的正常方式。 Which in turn causes the Run() method to return, which terminates the UI thread, which terminates the process. 这反过来导致Run()方法返回,终止UI线程,终止进程。

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. 现在,所有鼠标和键盘输入都会更改窗口大小或位置,它们不再用于以正常方式操作UI。 Releasing the mouse terminates that loop. 释放鼠标会终止该循环。 This dispatcher loop is built into the OS, it is not done by WPF. 这个调度程序循环内置在操作系统中,它不是由WPF完成的。

But WPF has use for such a modal loop as well. 但是WPF也可以用于这种模态循环。 The canonical example is the Window.ShowDialog() method. 规范示例是Window.ShowDialog()方法。 That method does not return until the dialog is closed. 在关闭对话框之前,该方法不会返回。 Achieved by WPF internally calling PushFrame() again. 由WPF内部再次调用PushFrame()实现。 Just try it with the debugger, you'll see both PushFrame calls in the Call Stack window. 只需使用调试器进行尝试,您将在“调用堆栈”窗口中看到两个PushFrame调用。 The first one is the one that ShowDialog() called, the second one is the one that Application.Run() called. 第一个是ShowDialog()调用的那个,第二个是Application.Run()调用的那个。 You'll get more if your dialog in turn displays a dialog. 如果您的对话框依次显示对话框,您将获得更多。

A less obvious example is calling Dispatcher.Invoke() on the UI thread. 一个不太明显的例子是在UI线程上调用Dispatcher.Invoke()。 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. 通常有点像一个bug,但没有令人信服的理由不允许它。 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. 使DoEvents()方法如此臭名昭着的错误。 A big reason why ShowDialog() disables all the other windows in your UI. ShowDialog()禁用UI中所有其他窗口的一个重要原因。

For what purposes is PushFrame used? PushFrame用于什么目的?

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 了解Dispatcher队列

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 您将在GitHub上的Stephen Cleary的AsyncCTPUtil库中找到具体的示例实现: 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? 如何同步运行异步Task <T>方法?

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 您还可以参考以下链接: https//social.msdn.microsoft.com/Forums/vstudio/en-US/650e69f9-5f4d-4d77-8107-93fb6646f26d/solved-block-synchronous-method-while-waiting -用于-异步法对完成?论坛= WPF

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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