我希望能够报告长时间运行的PLINQ查询的进度。
我无法找到任何本地的LINQ方法来实现这一点(就像取消一样实现)。
我阅读了这篇文章,其中展示了一个适用于常规序列化查询的简洁扩展函数。
我一直在使用下面的代码进行测试行为。
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的评论后,我发现它实际上是并行工作的,但我得到了如此多的进度报告,处理这么多进度报告会显著减慢我的测试/应用程序。
有没有一种并行/线程安全的方法以增量方式报告PLINQ的进度,以便用户知道正在取得进展,而对方法运行时间影响不大?
WithProgressReporting()
方法不能满足你的需求?通常,你会从IEnumerable<T>
开始...只需将源IEnumerable<T>
包装在调用WithProgressReporting()
的语句中,并在其中调用AsParallel()
,就像你在测试中所做的那样。最终吞吐量将是相同的,无论你在源或结果上报告进度。你需要更具体:发布一个[mcve]并精确地解释你期望的输出以及你实际得到的输出。 - Peter Duniho