为什么需要 PushFrame?

For what is PushFrame needed?

我遇到了 Dispatcher 对象的 PushFrame 方法。它是方法的简化版本:

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

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

    _frameDepth--;
    // Stuff
}

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

For what purposes is PushFrame used?

它在内部用于将帧推送到当前调度程序。调度程序队列如何详细工作是一个很大的话题,但以下答案应该会有所帮助。

Understanding the Dispatcher Queue

Is there good examples of its usage?

例如,当您出于某种原因想要同步调用异步方法并继续发送消息直到任务完成时。您将在 GitHub 上的 Stephen Cleary 的 AsyncCTPUtil 库中找到具体示例实现:https://github.com/StephenCleary/AsyncCTPUtil/blob/master/AsyncTestUtilities/WpfContext.cs

更多信息请参考他的回答:

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

您还可以参考以下内容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

它是 WPF 程序中调度程序循环的基本管道。 Windows上的每个GUI程序都有一个,它是producer-consumer problem的通用解决方案。 OS 和其他程序生成以及 WPF 程序的 UI 线程消耗的位置。 GUI 应用程序的硬性要求,实现 GUI 的库代码永远不会是 thread-safe。这里很容易看到循环,看不到循环清空的thread-safe队列,它内置在OS.

循环是通过调用 Application.Run() 开始的。在 WPF 应用程序中不容易看到,它在您的 App.xaml 文件中的大多数应用程序中是 auto-generated。这会推动第一个 "frame",只要它留在循环内,您的应用就会保持 运行。当您在事件处理程序上设置断点时,您将始终在调用堆栈调试器 window 中看到它。关闭应用程序的主窗口是循环结束的正常方式。这反过来会导致 运行() 方法 return,从而终止 UI 线程,从而终止进程。

在某些情况下,您希望有一个嵌套的调度程序循环。一个"modal loop"。您每天使用的此类模态循环的一个示例是当您在 window 角上单击并拖动鼠标时。所有鼠标和键盘输入现在都改变了 window 的大小或位置,它们不再用于以正常方式操作 UI。释放鼠标终止该循环。此调度程序循环内置于 OS,它不是由 WPF 完成的。

但是 WPF 也可以使用这种模态循环。典型的例子是 Window.ShowDialog() 方法。在对话框关闭之前,该方法不会 return。通过 WPF 内部再次调用 PushFrame() 实现。只需使用调试器尝试一下,您就会在调用堆栈 window 中看到两个 PushFrame 调用。第一个是 ShowDialog() 调用的那个,第二个是 Application.Run() 调用的那个。如果您的对话框依次显示一个对话框,您会得到更多。

一个不太明显的例子是在 UI 线程上调用 Dispatcher.Invoke()。在调用方法 return 之前不会 return 的方法。通常有点错误,但没有令人信服的理由禁止它。一句警告可能是合适的,模态循环非常危险。他们有制造 re-entrancy bug 的诀窍。使 DoEvents() 方法臭名昭著的那种错误。 ShowDialog() 禁用 UI.

中所有其他 windows 的一个重要原因