【问题标题】:For what is PushFrame needed?PushFrame 需要什么?
【发布时间】:2017-01-21 01:42:51
【问题描述】:

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

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

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

    _frameDepth--;
    // Stuff
}

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

【问题讨论】:

标签: c# wpf dispatcher


【解决方案1】:

它是 WPF 程序中调度程序循环的基本管道。 Windows 上的每个 GUI 程序都有一个,它是producer-consumer problem 的通用解决方案。操作系统和其他程序的生成位置以及 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 中所有其他窗口的一个重要原因。

【讨论】:

  • 很好的解释。谢谢
  • 两个问题: • PushFrame 是否会阻止执行——因此在此帧执行期间的任何进程都必须在单独的线程上执行? • 这是否会导致应用程序在框架继续时保持响应 (DispatcherFrame.Continue == true)?
【解决方案2】:

PushFrame 用于什么目的?

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

Understanding the Dispatcher Queue

有没有很好的用法例子?

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

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

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

您也可以参考以下链接: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

【讨论】:

    猜你喜欢
    • 2019-06-09
    • 1970-01-01
    • 2015-01-26
    • 2020-12-14
    • 2012-03-11
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 2012-09-16
    相关资源
    最近更新 更多