C#等待收藏

时间:2017-05-28 18:45:47

标签: c# asynchronous collections task

有没有一种标准的方法来等待一个集合被另一个任务标记为完成(线程?)我正在寻找像await collection.Completion.Task

这样的东西

到目前为止,我发现了以下方法:

  • 使用TaskCompletionSource变量(需要与其他任务/线程共享)
  • 使用BlockingCollection并执行while(!collection.IsAddingCompleted) {}(非异步)
  • 使用TPL数据流中的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();
    }
}

1 个答案:

答案 0 :(得分:3)

  

有没有一种标准的方法来等待一个集合被另一个任务标记为完成?

您可以使用任何类型的“信号”。由于这只是一次性信号,TaskCompletionSource<T>会很好。事实上,它是一个收集完成的信号是无关紧要的。但是,正如您所发现的,某些集合确实具有此内置功能。<​​/ p>

解决您的每个问题:

  • TaskCompletionSource<T> - 最简单的IMO,因为它可以用于任何类型的集合。
  • BlockingCollection<T> - 你不想使用BlockingCollection,但你可以使用AsyncProducerConsumerQueue or AsyncCollection,它们是相同的抽象但允许异步等待。
  • BufferBlock<T> - 也没关系。很多人使用BufferBlock<T>作为异步兼容的生产者/消费者队列。
  • ObservableCollection<T> - 不是一个选项,因为它没有“完成”的概念。
  • 其他 - 如果您的收藏品是“基于推送”的,则可以使用IObservable<T>而只使用await