【发布时间】:2019-04-09 02:02:16
【问题描述】:
我想报告长期运行的 PLINQ 查询的进度。
我真的找不到任何允许我这样做的本机 LINQ 方法(就像 implemented 用于 cancellation 一样)。
我读过this article,它显示了一个用于常规序列化查询的简洁扩展函数。
我一直在使用以下代码测试行为。
var progress = new BehaviorSubject<int>(0);
DateTime start = DateTime.Now;
progress.Subscribe(x => { Console.WriteLine(x); });
Enumerable.Range(1,1000000)
//.WithProgressReporting(i => progress.OnNext(i)) //Beginning Progress
.AsParallel()
.AsOrdered()
//.WithProgressReporting(i => progress.OnNext(i)) //Middle Progress reporting
.Select(v => { Thread.Sleep(1); return v * v; })
//.WithProgressReporting(i => progress.OnNext(i)) //End Progress Reporting
.ToList();
Console.WriteLine("Completed in: " + (DateTime.Now - start).TotalSeconds + " seconds");
编辑:
使用IEnumerable<T> 扩展从中间报告进度会删除并行性。
结束报告在计算并行计算时不报告任何进度,然后在最后快速报告所有进度。我认为这是将并行计算的结果编译成列表的过程。
我最初认为 开始 的进度报告导致 LINQ 无法并行运行。在对此进行睡眠并从Peter Duniho 读取cmets 之后,我发现它实际上是并行工作的,但是我收到了很多进度报告,处理这么多导致我的测试/应用程序显着变慢。
是否有一种并行/线程安全的方法可以从 PLINQ 以增量方式报告进度,从而允许用户知道正在取得的进度,而不会对方法运行时产生重大影响?
【问题讨论】:
-
你的问题不是很清楚。为什么非并行
WithProgressReporting()方法不能充分满足您的目的?通常,无论如何,您都将从IEnumerable<T>开始......只需将您的源代码IEnumerable<T>与WithProgressReporting()的调用一起调用,然后再调用AsParallel(),就像您在测试中所做的那样。最终吞吐量将是相同的,无论您报告源还是结果的进度。您需要更具体:发布minimal reproducible example 并准确地解释您期望的输出,以及您得到的结果。
标签: c# .net linq parallel-processing