有没有一种标准的方法来等待一个集合被另一个任务标记为完成(线程?)我正在寻找像await collection.Completion.Task
到目前为止,我发现了以下方法:
TaskCompletionSource
变量(需要与其他任务/线程共享)BlockingCollection
并执行while(!collection.IsAddingCompleted) {}
(非异步)BufferBlock<T>
并执行await bufferBlock.Completion.Task
(可能需要大量开销?)ObservableCollection
(非异步)所有的想法都赞赏
编辑:添加方案以提供更多上下文
class Program
{
static void Main(string[] args)
{
var list = new List<int>();
var tcs = new TaskCompletionSource<bool>();
//This thread represents an independent process which will populate the list
new Thread(() =>
{
for (int i = 0; i < 5; i++)
{
Thread.Sleep(200); // do work
list.Add(i);
}
tcs.SetResult(true);
Thread.Sleep(2000); //do more work
Console.WriteLine("The End -- Press Enter");
Console.ReadLine();
}
).Start();
//This task awaits for the list to be populated
new Task(async () =>
{
await Task.Delay(300); //do work
await tcs.Task;
Console.WriteLine("List count = " + list.Count);
}).Start();
}
}
答案 0 :(得分:3)
有没有一种标准的方法来等待一个集合被另一个任务标记为完成?
您可以使用任何类型的“信号”。由于这只是一次性信号,TaskCompletionSource<T>
会很好。事实上,它是一个收集完成的信号是无关紧要的。但是,正如您所发现的,某些集合确实具有此内置功能。</ p>
解决您的每个问题:
TaskCompletionSource<T>
- 最简单的IMO,因为它可以用于任何类型的集合。BlockingCollection<T>
- 你不想使用BlockingCollection
,但你可以使用AsyncProducerConsumerQueue
or AsyncCollection
,它们是相同的抽象但允许异步等待。BufferBlock<T>
- 也没关系。很多人使用BufferBlock<T>
作为异步兼容的生产者/消费者队列。ObservableCollection<T>
- 不是一个选项,因为它没有“完成”的概念。IObservable<T>
而只使用await
。