Skip to main content
 首页 » 编程设计

C# 等待集合

2024年02月27日31lyhabc

是否有标准的方法来等待另一个任务(线程)将集合标记为完成?我正在寻找类似 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 , 但你可以使用 AsyncProducerConsumerQueue or AsyncCollection ,它们是相同的抽象,但允许异步等待。
  • BufferBlock<T> - 也很好。很多人用BufferBlock<T>作为异步兼容的生产者/消费者队列。
  • ObservableCollection<T> - 不是一个选项,因为它没有“完成”的概念。
  • 其他 - 如果您的收藏是“基于推送”的,您可以使用 IObservable<T>只是await