我知道Task Parallel Library仍处于 Beta 阶段,可用资源可能较少,但无论我读过什么,库对任务调度、异常处理和取消都给予了非常特殊的处理。
但我没有找到任何关于进度报告和发送任务增量结果的参考。这两件事似乎太重要了,不容忽视。您能否介绍一下如何在任务并行库中处理这些问题或参考一些解释它们的文章?
我知道Task Parallel Library仍处于 Beta 阶段,可用资源可能较少,但无论我读过什么,库对任务调度、异常处理和取消都给予了非常特殊的处理。
但我没有找到任何关于进度报告和发送任务增量结果的参考。这两件事似乎太重要了,不容忽视。您能否介绍一下如何在任务并行库中处理这些问题或参考一些解释它们的文章?
此示例更新进度条:
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++; });
});
});
}
}
这是我的热门搜索结果之一,但Task Parallel Library
这里仍然没有进展的例子......
今天我刚刚遇到了 TPL,因为我想开发新的多线程应用程序但没有使用BackgroundWorker
(因为我之前在某处读过关于任务的好代码)
我从@Stephen Cleary 的答案中编译了这个例子,他的链接非常复杂,以寻找进度,以及其他一些网站。
这是一个非常简单的示例,说明如何使用 UI 线程安全方式进行Progress和Completed :
TaskScheduler currentTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task<string>.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,然后附加“完成!” windows窗体标题栏中的字符串。您可以看到 TaskScheduler 是创建 UI 线程安全更新的棘手方法,因为我认为任务计划在主线程上运行。
没有像 BackgroundWorker 那样的内置支持。
可以直接使用 SynchronizationContext;这里有一个很棒的视频: http ://www.rocksolidknowledge.com/ScreenCasts.mvc/Watch?video=TasksAndThreadAffinity.wmv
作者在此视频中开发了两种解决方案:一种使用 SynchronizationContext,另一种使用 Task Continuations。对于您的问题,延续将不起作用,但 SynchronizationContext 方法可以正常工作。
PS 如果您正在创建可重用的代码,那么当您捕获 SynchronizationContext.Current 时,您应该测试 null 并且(如果它为 null)使用默认构造的 SynchronizationContext。
更新:我已经在我的博客上发布了代码。我的解决方案实际上是基于 aTask
调度回 UI 线程的TaskScheduler
,它SynchronizationContext
在下面使用。与公认的答案不同,此解决方案适用于 WPF 和 Windows 窗体。
TPL 并不是特别面向 UI 支持,您可以(仍然)为此使用 BackgroundWorker。至于发送或处理中间结果,有新的集合类(ConcurrentQueue)来支持它。