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

时间:2013-09-11 08:57:18

标签: c# multithreading events

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

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

4 个答案:

答案 0 :(得分: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.
  }

}

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

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

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

如果要添加正常终止,您可以使用task cancellation mechanisms来弹出GetConsumingEnumerable枚举器。我没有说明这可以在这里,但它并不是非常困难,并且已经有很多例子。

答案 1 :(得分:2)

我会考虑使用TPL DataFlow中的ActionBlock - 特别是如果没有要求按顺序处理消息的话。作为奖励,无需在代码中管理消费者线程。

以下是一个例子:

 // Create an ActionBlock that performs some work. 
 var workerBlock = new ActionBlock<MessageData>(

  data=>
     {
         DoWork(data); // method consuming data
     },

  // Specify a maximum degree of parallelism. 
  new ExecutionDataflowBlockOptions
  {
     MaxDegreeOfParallelism = maxDegreeOfParallelism
  });

// Post messageCount messages to the queue
for (int i = 0; i < messageCount; i++)
 {
   var messageData = new MessageData();
   workerBlock.Post(messageData);
 }

 // Signal that Producer has no more data to send
 workerBlock.Complete();

 // Wait for all messages to propagate through the network.
 workerBlock.Completion.Wait();

答案 2 :(得分:1)

ObservableCollection模板类可能是您问题的解决方案:

http://msdn.microsoft.com/en-us/library/ms668604.aspx

  

表示在何时提供通知的动态数据集合   项目被添加,删除或刷新整个列表。

答案 3 :(得分:0)

一个非常简单的方法是,当主线程准备好使用数据时,主线程只需生成带有数据副本的线程池线程。无需发出信号;无需运行后台线程。