了解Dispatcher队列

时间:2012-07-10 15:55:14

标签: c# wpf asynchronous dispatcher method-invocation

我认为我需要一些帮助来理解 Dispatcher Queue

当新工作到达时,它会在调度程序队列的开头添加,并且当Dispatcher想要处理工作项时,它会从头开始删除。

更一般地说:如果有工作,它会以FIFO方式存储在队列中,并且只要没有工作就可以处理。

MSDN文档here指的是loopframe

The Dispatcher processes the work item queue in a loop. The loop is referred to as a frame.

但在这种情况下,循环在哪里?对我来说,循环是迭代某些东西的东西,当它到达终点时,它会重新开始。

frame的概念是什么?根据MSDN文档,框架是队列中工作项的一击?如果这是真的,应该如何使用静态方法Disptatcher.PushFrame()

最有趣的问题是,是否有任何方法可以获取队列的当前状态,尤其是队列中有多少项。

如果之前调用的方法(以及因此放入Dispatcher队列中)被执行,然后立即从队列中删除,或者在内部持续一段时间,它是否成立?

我知道,这么多问题: - )

1 个答案:

答案 0 :(得分:25)

围绕Dispatcher的文档非常少,因此您需要对其进行反汇编以了解内部工作原理。

调度程序基本上是围绕应用程序Message Pump执行工作的东西。有问题的一个位于windows message loop

之上

因此,只能有一个应用程序Dispatcher - Application.Current.Dispatcher可访问的全局调度程序对象。其他调度员可以通过访问Dispatcher.CurrentDispatcher来实现,根据文档

  

获取当前正在执行的线程的Dispatcher并创建一个   new Dispatcher如果尚未与该线程关联。

但是,在此新调度程序上调用Run将会阻止。

执行Dispatcher.PushFrame时,它基本上将帧推送到当前的调度程序。从DispatcherObject继承的任何内容(例如DispatcherFrame)都会将其调度程序设置为当前的调度程序。我们可以通过查看它的构造函数来验证这一点。

private Dispatcher _dispatcher;

protected DispatcherObject()
{
    this._dispatcher = Dispatcher.CurrentDispatcher;
}

当然,拥有一个简单的事件循环是不够的 - 有时您需要破坏当前的事件循环以强制完成其他工作。这就是你有DispatcherFrame的原因。这实际上构成了事件循环。当您将帧推入Dispatcher时,会发生以下情况:

while (frame.Continue)
        {
            if (!this.GetMessage(ref msg, IntPtr.Zero, 0, 0))
            {
                break;
            }
            this.TranslateAndDispatchMessage(ref msg);
        }

TranslateAndDispatchMessage中,在取消消息后,Dispatcher中的优先级队列被评估。

如果一个操作需要很长时间才能在调度程序上运行,它会暂时停止事件循环,并且因为它不响应信号,应用程序似乎停止响应。

Here's an article使用框架强制UI响应,允许事件循环很快运行。

对于访问队列,实际上,无法知道Dispatcher外部队列的状态。这是一个内部细节,它没有暴露是合理的。