很少有关于
Dispatcher
的文档,因此您需要分解一下才能了解其内部工作原理。
调度程序基本上是在应用程序的
Message Pump周围执行工作的东西。其中一个问题位于
windows message loop之上。
因此,只能有一个应用程序调度程序 - 通过
Application.Current.Dispatcher
访问的全局调度程序对象。通过访问
Dispatcher.CurrentDispatcher
可以使用其他调度程序,根据文档,它会
获取当前正在执行的线程的Dispatcher,并在尚未与该线程关联时创建新的Dispatcher。
但是,在这个新调度程序上调用
Run
将会阻塞。
当您执行
Dispatcher.PushFrame
时,它会将一个内部执行循环推入到Dispatcher中 - 这是
frame的一般想法。任何从
DispatcherObject
继承的内容,例如
DispatcherFrame
,其调度程序将设置为当前调度程序。我们可以通过查看其构造函数来验证这一点。
private Dispatcher _dispatcher;
protected DispatcherObject()
{
this._dispatcher = Dispatcher.CurrentDispatcher;
}
当然,仅有一个简单的事件循环是不够的 - 有时您需要颠覆当前事件循环以强制执行其他工作。这就是为什么您需要一个
DispatcherFrame
。这实际上构成了事件循环。当您将框架推入调度程序时,会发生以下情况:
while (frame.Continue)
{
if (!this.GetMessage(ref msg, IntPtr.Zero, 0, 0))
{
break;
}
this.TranslateAndDispatchMessage(ref msg);
}
在TranslateAndDispatchMessage
中,调度程序中的优先级队列在消息被取出后得到评估。
如果一个操作在调度程序上运行的时间很长,它会暂时停止事件循环,并且由于它不响应信号,应用程序似乎停止响应。
这里是一篇文章,它使用一个框架来强制UI响应,通过允许事件循环短暂运行。
至于访问队列,目前没有办法在调度程序外部了解队列的状态。这是一个内部细节,不公开是合理的。