【问题标题】:How does the Parallel.Foreach/For call the BlockingCollection.Take? with or without CancellationTokenParallel.Foreach/For 如何调用 BlockingCollection.Take?有或没有 CancellationToken
【发布时间】:2013-09-28 15:39:17
【问题描述】:
         try
         {
             ParallelOptions Options = new ParallelOptions();
             Options.CancellationToken = base.DownloadCancellation.Token;
             Parallel.ForEach(base.BlockingCollection1, Options, ActiveSeeder =>
                 {
                     //...
                 });
         }
         catch
         {
             if (base.DownloadCancellation.IsCancellationRequested)
                 return false;
         }

Parallel.Foreach/For 是否调用 BlockingCollection1.Take 函数我放入 ParallelOptions 的 CancellationToken 有还是没有?

有机会知道吗?

【问题讨论】:

    标签: c# multithreading parallel.foreach blockingcollection cancellationtokensource


    【解决方案1】:

    Parallel.ForEach() 根本没有 调用Take(),所以你的问题是无效的。

    相反,它会像对待任何其他IEnumerable<T> 一样处理该集合,这意味着它将调用其GetEnumerator(),然后处理结果。 What GetEnumerator() does for BlockingCollection is documented:

    GetConsumingEnumerable 不同,BlockingCollection<T>.IEnumerable<T>.GetEnumerator 返回一个不修改基础集合的标准枚举器。如果在调用GetEnumerator 时其他线程正在同时添加或删除元素,则枚举器返回的元素可能不代表集合的当前状态。

    如果您想在迭代时从集合中删除项目,您可以使用GetConsumingEnumerable(),它确实有an overload that takes CancellationToken。但这实际上不会很好地工作,所以最好使用GetConsumingPartitioner() from ParallelExtensionsExtras (code on GitHub)。

    【讨论】:

    • GetConsumingPartitioner 的链接现已失效。 :(
    • @Vaccano 感谢您告诉我,我已经更新了链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多