子线程处理由Parent引发的事件

liu*_*uda 2 c# events multithreading

我想要达到的目标与标题相同.在我的问题中,我的主线程中有一个数据列表,我希望主线程触发一个事件,子线程可以处理该事件以使用数据列表.无论如何在C#中做到这一点?

我首先想到的方法是让子线程不断检查数据列表.但我想通过让主线程通知子线程,我可以节省让子线程在后台不断运行的开销.

Bri*_*eon 5

你应该在这里使用生产者 - 消费者模式.父线程将充当生产者,子线程将充当消费者.父母将生成数据并以这样的方式发布它,以便通知孩子(无需轮询),以便它可以使用它.幸运的是,.NET使这一BlockingCollection课变得简单.这是您的代码可能是什么样子.

class Producer
{
  private BlockingCollection<YourData> queue;

  public Producer(BlockingCollection<YourData> q)
  {
    queue = q;
  }

  public void GenerateItems()
  {
    while (...)
    {
      YourData item = GenerateItem();
      queue.Add(item);
    }
  }
}

class Consumer
{
  public Consumer(BlockingCollection<YourData> queue)
  {
    Task.Factory.StartNew(
      () =>
      {
        foreach (YourData item in queue.GetConsumingEnumerable())
        {
          ProcessItem(item);
        }
      ), TaskCreationOptions.LongRunning);
  }

  private void ProcessItem(YourData item)
  {
    // Add logic to process each data item here.
  }

}
Run Code Online (Sandbox Code Playgroud)

因此,我们有一个Producer生成数据项的类,并将它们添加到BlockingCollection一个Consumer类中,该类在可用时删除这些数据项.GetConsumingEnumerable表现如下Take:如果队列中没有任何内容,它会将调用者置于空闲状态.所以基本上调用线程没有进行任何类型的繁忙轮询(至少不是在微不足道的意义上),所以它是资源友好的.

这是一个如何粘合在一起的例子.

public static void Main()
{
  var queue = new BlockingCollection<YourData>();
  var producer = new Producer(queue);
  var consumer = new Consumer(queue);
  producer.GenerateItems();
}
Run Code Online (Sandbox Code Playgroud)

如果要添加正常终止,可以使用任务取消机制GetConsumingEnumerable弹出枚举器.我没有说明这可以在这里,但它并不是非常困难,并且已经有很多例子.