支持.NET 4.0“任务并行库”中的进度报告和增量结果

我知道任务并行库仍处于测试阶段,并且可能有更少的资源可用,但是从我读过的内容来看,库为任务调度 , exception处理和取消提供了非常特殊的处理。

但我没有找到任何关于进度报告和从任务发送增量结果的引用。 这两件事似乎太重要了,不容忽视。 您能否详细介绍如何在任务并行库中处理这些内容或参考一些解释它们的文章?

此示例更新进度条:

using System; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; class SimpleProgressBar : Form { [STAThread] static void Main(string[] args) { Application.EnableVisualStyles(); Application.Run(new SimpleProgressBar()); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); int iterations = 100; ProgressBar pb = new ProgressBar(); pb.Maximum = iterations; pb.Dock = DockStyle.Fill; Controls.Add(pb); Task.ContinueWith(delegate { Parallel.For(0, iterations, i => { Thread.SpinWait(50000000); // do work here BeginInvoke((Action)delegate { pb.Value++; }); }); }); } } 

从Parallel.For内部更新进度条

这是我最热门的搜索结果之一,仍然没有在这里Task Parallel Library进展示例…

今天我刚刚遇到TPL,因为我想开发新的multithreading应用程序,但没有使用BackgroundWorker (因为我之前用一些很好的代码读过有关任务的任务)

我从@Stephen Cleary回答编译示例,他的链接相当复杂,以寻找进度,以及其他一些网站。

这是如何使用UI线程安全方式执行ProgressCompleted的非常简单的示例:

  TaskScheduler currentTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); Task.Factory.StartNew(() => { // loop for about 10s with 10ms step for (int i = 0; i < 1000; i++) { Thread.Sleep(10); Task.Factory.StartNew(() => { // this is a task created each time you want to update to the UI thread. this.Text = i.ToString(); }, CancellationToken.None, TaskCreationOptions.None, currentTaskScheduler); } return "Finished!"; }) .ContinueWith(t => { // this is a new task will be run after the main task complete! this.Text += " " + t.Result; }, currentTaskScheduler); 

代码将在10秒内显示1到1000,然后附加“完成!” 窗体中的字符串forms标题栏。 您可以看到TaskScheduler是创建UI线程安全更新的棘手方法,因为我认为任务计划在主线程上运行。

没有像BackgroundWorker那样的内置支持。

您可以直接使用SynchronizationContext; 这里有一个很棒的video: http : //www.rocksolidknowledge.com/ScreenCasts.mvc/Watch? video = TasksAndThreadAffinity.wmv

作者在此video中开发了两个解决方案:一个使用SynchronizationContext,另一个使用Task Continuations。 对于您的问题,continuation将不起作用,但SynchronizationContext方法将正常工作。

PS如果您正在创建可重用的代码,那么当您捕获SynchronizationContext.Current时,您应该测试null并且(如果它为null)使用默认构造的SynchronizationContext。

更新 :我在我的博客上发布了此代码。 我的解决方案实际上是基于TaskScheduler调度回UI线程的Task ,后者使用SynchronizationContext 。 与接受的答案不同,此解决方案适用于WPF和Windows窗体。

TPL并不是特别针对UI支持,您可以(仍然)使用BackgroundWorker。 至于发送或处理中间结果,有新的集合类(ConcurrentQueue)来支持它。

要报告异步任务的进度,请将IProgress传递给async方法。 在该方法中,使用进度数据调用Report 。 调用者可以决定如何处理该进度报告(即忽略它或更新UI)。