C# 如何在另一个线程填充IEnumerable时枚举该IEnumerable

C# 如何在另一个线程填充IEnumerable时枚举该IEnumerable,c#,multithreading,collections,thread-safety,C#,Multithreading,Collections,Thread Safety,我希望在同一台机器上有两个线程,一个用于填充集合,另一个用于在数据可用时立即从中弹出数据,并在知道结束时停止。 我只是不知道该用什么收藏 private void DataProviderThread() { GlobalCollection = new SomeMagicCollection(); for (int i = 0; i < 100; i++) { GlobalCollection.Add(new SomeDataItem(i));

我希望在同一台机器上有两个线程,一个用于填充集合,另一个用于在数据可用时立即从中弹出数据,并在知道结束时停止。 我只是不知道该用什么收藏

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  
}
private void数据提供者线程()
{
GlobalCollection=新的SomeMagicCollection();
对于(int i=0;i<100;i++)
{
添加(新的SomeDataItem(i));
睡眠(100);
}
GlobalCollection.i已完成人口统计汉克和耶();
}
私有void DataCruncherThread()
{
foreach(GlobalCollection中的var项)
{
//做任何事
}
//只有在数据提供程序声明收集已完成时,该控件才应退出foreach
}
然后,我想简单地对它进行迭代,让集合负责

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

我不敢相信C#没有在新版本中发布这个。但是它的名字是什么?

你拥有的是一个经典的生产者/消费者模式

您可以使用
ConcurrentQueue
或者更好的方法是使用

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


它是一个
IEnumerable
,但不要试图像非共享集合那样使用它。
TryTake()
方法是获取数据最有用的方法

ConcurrentQueue可能重复:使用它作为
IEnumerable
访问数据是一种非常好的方法,或者如果情况允许,使用它作为
GetConsumineumerable
。我发现我很少需要使用
Take
或TryTake`,因为这两个选项都是为了在从其他线程修改集合时使用。对于某些类型的操作,只要知道并发性,使用IEnumerable接口是可以的。我不认为消费者可以很清楚地使用,但这是一个品味的问题。你不认为它很清楚与它不起作用有很大的不同。这两个操作在很大程度上都是为在多线程上下文中使用而设计的。