1
         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?

有机会知道吗?

4

1 回答 1

5

Parallel.ForEach()根本打电话Take(),所以你的问题是无效的。

相反,它将像对待任何其他集合一样对待集合IEnumerable<T>,这意味着它将调用它GetEnumerator(),然后处理结果。记录什么GetEnumerator()BlockingCollection

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

如果您想在迭代时从集合中删除项目,您可以使用GetConsumingEnumerable(),它确实有一个需要CancellationToken. 但这实际上不会很好地工作,因此最好GetConsumingPartitioner()从 ParallelExtensionsExtrasGitHub 上的代码)中使用。

于 2013-09-28T16:19:21.417 回答