如何在另一个线程填充IEnumerable时枚举它

时间:2015-02-17 17:04:30

标签: c# multithreading collections thread-safety

我想在同一台机器上安装两个线程,一个用于填充集合,另一个用于在数据可用时立即弹出数据,并在知道结束时停止。 我只是不知道要使用什么样的集合......

private void DataProviderThread()
{
    GlobalCollection = new SomeMagicCollection();

    for (int i = 0; i < 100; i++)
    {
        GlobalCollection.Add(new SomeDataItem(i));
        Thread.Sleep(100);
    }

    GlobalCollection.IHaveFinishedPopulatingThanksAndBye();
}

private void DataCruncherThread()
{
    foreach (var item in GlobalCollection)
    {
        // Do whatever
    }
    // The control should exit foreach only once the data provider states that the collection is finished  
}

然后我想简单地迭代它,让Collection处理

  • 保持线程安全
  • 授予标准IEnumerable功能
  • 让我的数据cruncher线程等待新项目,直到DataBuilder明确地调用IHaveFinishedPopulatingThanksAndBye(),然后干净地退出循环
  • 允许我让其他几个线程使用相同的约束进行迭代

我无法相信C#不会在新版本中发布此版本。但它的名字是什么?

1 个答案:

答案 0 :(得分:8)

您拥有的是经典的制作人/消费者模式。

您可以使用ConcurrentQueue<T>或更好的BlockingCollection<T>

BoundedCapacity属性允许您调节(限制)数据流。

这是IEnumerable<T>但不要尝试像非共享收藏一样使用它。 TryTake()方法是获取数据最有用的方法。