如何唤醒特定线程?

时间:2015-09-03 19:41:01

标签: c# multithreading

我有一堆线程被阻塞等待消息。每条消息都有一个指向特定线程的ID。我有以下实现:

1)所有线程都使用Monitor.Wait在同一个锁对象上等待。当收到消息时,我调用Monitor.PulseAll并且每个线程使用消息ID检查自己的ID。如果匹配,则线程继续。否则它会再次在同一个对象上等待。使用这种方法,每个消息到达都会导致N-1个线程被唤醒并且ID不匹配并重新进入休眠状态。

2)每个线程创建一个ManualResetEvent并将其添加到字典中。字典将消息id映射到其事件。当消息到达时,它会调用map[message.Id].Set()来唤醒特定的线程。

3)最后一个实现与#2非常相似,只是它使用了一个锁对象而不是ManualResetEvent。假设ManualResetEvent是一个昂贵的对象。与ManualResetEvent相比,这种方法更复杂。

这里最好的方法是什么?还有更好的吗?

2 个答案:

答案 0 :(得分:3)

问题描述相当模糊,因此很难确定您的最佳方法是什么。那说......

我根本不会使用#1或#2。 #1需要唤醒每个线程,因此一个线程可以运行,这显然效率低下,而#2使用非托管的基于Windows的同步对象,效率不高使用内置的.NET机制。

鉴于问题描述,您的#3选项面对它并非不合理。但是,恕我直言,你不应该自己重新实现这一点。即就我所知,你(由于某种原因)有需要提供给特定线程的消息,即给定的消息必须只由一个特定的线程处理。

在这种情况下,我认为您应该为每个线程创建一个单独的消息队列,并将消息添加到适当的队列中。有很多方法可以实现队列,但对于这个特定的例子来说,最明显的是使用BlockingCollection<T>。默认情况下,它使用队列作为基础集合数据结构。另一个重要的功能是GetConsumingEnumerable()方法,它允许您在依赖线程中编写foreach循环,以便在排队时检索消息。当没有消息可用时,循环将阻塞,等待通过其他线程提供消息。

您可以使用字典将消息ID映射到每个线程的相应队列。


请注意,这不是真的恕我直言的性能问题。它更多的是针对给定问题使用适当的数据结构。即您似乎有一个消息队列,您希望根据其ID将每个消息分派到不同的线程。相反,我认为您应该实现多个消息队列,每个线程一个,然后使用现有的.NET功能来实现您的逻辑,这样您就不必重新发明轮子。

另请注意,如果您仍然必须为邮件维护单个输入队列(例如,因为该界面呈现给您程序中的某个其他组件),您仍然可以并且仍然应该执行上述操作。您只需要一些适配器代码,这些代码可以从主要的单个消息队列中取消消息,并路由到相应的特定于线程的队列。

答案 1 :(得分:0)

  1. 唤醒特定主题或甚至开始主题 - Thread.Start()
  2. 检查您的帖子是否还没有中止 - Thread.IsAlive属性。
  3. 检查线程是否正在运行 - Thread.ThreadState()
  4. 您可以使用上述三种道具和方法对线程进行所需的控制,并以非常精细的粒度进行管理。

    初始化线程时,请将它们全部放在Dictionary<ID, Thread>()中。现在,无论何时收到消息,只需获取具有所需ID的线程并将其唤醒即可。