它是如何工作的?

在阅读Dispatcher类的文档之后,我意识到它也可以用于非UI排队的操作。

那么Dispatcher类实际上如何工作? 我意识到这一点,主要的工作是将动作排队到特定的线程 - 但它如何将这些动作“发送”到线程? 线程如何“获取”这些操作?

我最好的猜测是每个线程都有一些“线程队列”,但是我再也不知道了。


让一个线程开始执行代码到另一个线程并不是一件容易的事情。 问题的关键是你不能简单地告诉任何线程在该线程已经启动之后开始执行一个方法。 目标线程必须专门设置以提前接收这些请求。

通常使用的模式是生产者 - 消费者。 目标线程将围绕无限循环旋转,等待消息出现在阻塞队列中。 该队列被设计为阻塞,直到项目出现在队列中,从而防止目标线程不必要地占用CPU时间。 这是一个非常简单的方法来让线程接受注入委托来执行。

public class Example
{
  private BlockingCollection<Action> queue = new BlockingCollection<Action>();

  public Example()
  {
    new Thread(
      () =>
      {
        while (true)
        {
          Action action = queue.Take();
          action();
        }
      }).Start();
  }

  public void ExecuteAsync(Action action)
  {
    queue.Add(action);
  }
}

现在,在UI线程的情况下,它已经有一个消息循环运行,因此Dispatcher类可以简单地向包含要执行的委托的消息队列发布特殊消息。 在处理所有绘画,按钮点击等过程中,这个特殊消息也将被UI线程拾取,并且它将开始执行委托。

那么Dispatcher类实际上如何工作? 我意识到这一点,主要的工作是将动作排队到特定的线程 - 但它如何将这些动作“发送”到线程?

通过将委托排队到目标线程监视的队列中。

线程如何“获取”这些操作?

通过运行监视队列的无限循环。 队列通常是一种称为阻塞队列的特殊类型,如果队列为空,则阻塞消耗线程。

我最好的猜测是每个线程都有一些“线程队列”,但是我再也不知道了。

八九不离十。 除了线程实际上没有内置队列用于此目的。 它必须手动设置。 这就是为什么只有专门设计的线程才能接受委托注入。 UI线程以这种方式设置,因为Application.Run创建消息循环。 在我的例子中,你会看到我必须使用BlockingCollection和一个无限循环来让它在工作线程上工作。


那么,显然Dispatcher排队实现看起来像一个Win32消息泵,但它不是(尽管它使用相同的User32消息和线程模型)。


非常有趣的问题,但是你不需要一个Window来拥有一个消息队列,这些都是单独的概念,你可以通过调用PeekMessage在任何线程上创建一个消息队列。

欲了解更多信息,请看这里

但当然这并不意味着没有窗口的调度程序是有用的。 我可以假设设计人员正在考虑一个独立的Dispatcher对象,以便让它处理与应用程序一样多的窗口。

链接地址: http://www.djcxy.com/p/10259.html

上一篇: How does it work?

下一篇: xcodebuild arguments ignored when using archive