PushFrame有什么用途?

3

我发现了Dispatcher对象的PushFrame方法。它是该方法的简化版本:

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

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

    _frameDepth--;
    // Stuff
}

换句话说,它只是开启一个新的消息处理循环。但我真的无法理解这种方式的好处。PushFrame 用于什么目的?有使用它的好例子吗?对我来说,这种方法似乎会导致不明显的错误。


1
https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.pushframe.aspx - Chandan Rai
我阅读了文档。我知道它是如何工作的,但我无法理解这个方法的目的。为什么需要PushFrame方法? - Alex Aparin
2个回答

12

这是WPF程序中调度循环的基本管道。在Windows上的每个GUI程序都有一个,它是生产者-消费者问题的通用解决方案。操作系统和其他程序产生,您的WPF程序的UI线程消耗。对于GUI应用程序而言,这是一个硬性要求,实现GUI的库代码永远不是线程安全的。您可以在此处轻松查看循环,但无法看到由该循环清空的线程安全队列,因为它内置于操作系统中。

通过调用Application.Run()来启动循环。在WPF应用程序中很难看到它,大多数应用程序都是从App.xaml文件自动生成的。这将推送第一个“帧”,只要保持在循环内部,您的应用程序就会继续运行。当您在事件处理程序上设置断点时,您总是会在调用堆栈调试器窗口中看到它。关闭应用程序的MainWindow是循环结束的正常方式。这反过来导致Run()方法返回,终止UI线程,进而终止进程。

有一些情况下,您可能希望使用嵌套的调度程序循环,即“模态循环”。每天使用的此类模态循环示例是当您在窗口角落单击并拖动鼠标时。现在,所有鼠标和键盘输入都将更改窗口大小或位置,它们不再用于以正常方式操作UI。释放鼠标会终止该循环。该调度程序循环内置于操作系统中,而不是WPF执行。
但是,WPF也需要这样的模态循环。经典示例是Window.ShowDialog()方法。该方法直到对话框关闭后才返回。WPF通过再次调用PushFrame()来实现。只需使用调试器尝试它,您将在Call Stack窗口中看到两个PushFrame调用。第一个是ShowDialog()调用的,第二个是Application.Run()调用的。如果您的对话框反过来显示对话框,则会获得更多内容。
一个不太明显的例子是在UI线程上调用Dispatcher.Invoke()。这个方法直到被调用的方法返回才会返回。通常可能会有一些错误,但没有充分的理由来禁止它。需要警告一下,模态循环非常危险。它们有一种导致反复进入错误的技能。这种错误让DoEvents()方法如此臭名昭著。这也是为什么ShowDialog()会禁用UI中的所有其他窗口的主要原因。

很好的解释。谢谢。 - Alex Aparin
两个问题: • PushFrame是否会阻塞执行 - 因此,在此帧执行期间的任何进程都必须在单独的线程上执行? • 这会导致应用程序在继续帧时保持响应(DispatcherFrame.Continue == true)吗? - Adam L. S.

1
PushFrame有哪些用途?
它在内部用于将帧推送到当前调度程序上。调度程序队列的详细工作原理是一个很大的话题,但以下答案应该是有帮助的。 了解调度程序队列 它有很好的使用示例吗?
例如,当您出于某种原因想要同步调用异步方法并继续泵送消息直到任务完成时。您可以在Stephen Cleary的GitHub上的AsyncCTPUtil库中找到此类具体示例实现:https://github.com/StephenCleary/AsyncCTPUtil/blob/master/AsyncTestUtilities/WpfContext.cs 有关更多信息,请参阅他在此处的答案: 如何同步运行异步Task<T>方法? 你也可以参考以下链接: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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接