是否有标准的方法来等待另一个任务(线程)将集合标记为完成?我正在寻找类似 await collection.Completion.Task 的东西
到目前为止,我发现了以下方法:
- 使用
TaskCompletionSource变量(需要与其他任务/线程共享) - 使用
BlockingCollection并做一个while(!collection.IsAddingCompleted) {}(非异步) - 使用
BufferBlock<T>来自 TPL Dataflow 并执行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();
}
}
请您参考如下方法:
Is there a standard way to await for a collection to be marked as complete by another task?
您可以为此使用任何类型的“信号”。由于这只是一次性信号,TaskCompletionSource<T>会没事的。它是一个收集完成的信号这一事实并不重要。不过,正如您所发现的,某些集合确实内置了此功能。
解决您的每个问题:
-
TaskCompletionSource<T>- 最直接的 IMO,因为它可以用于任何类型的集合。 -
BlockingCollection<T>- 你不想使用BlockingCollection, 但你可以使用AsyncProducerConsumerQueueorAsyncCollection,它们是相同的抽象,但允许异步等待。 -
BufferBlock<T>- 也很好。很多人用BufferBlock<T>作为异步兼容的生产者/消费者队列。 -
ObservableCollection<T>- 不是一个选项,因为它没有“完成”的概念。 - 其他 - 如果您的收藏是“基于推送”的,您可以使用
IObservable<T>只是await
