具有多个任务和UI同步的WinForms TPL模式 – 这是正确的吗?

我是TPL(任务并行库)的新手,我想知道以下是否是最有效的方法来启动1个或多个任务,整理结果并在数据网格中显示它们。

  1. Search1和Search2与两个单独的数据库通信,但返回相同的结果。
  2. 我禁用按钮并打开微调器。
  3. 我正在使用一个ContinueWhenAll方法调用来关闭任务。
  4. 我已将调度程序添加到ContinueWhenAll调用以更新表单按钮,datagrid,并关闭微调器。

问:我这样做是对的吗? 有没有更好的办法 ?
问:我如何为此添加取消/exception检查?
问:如果我需要添加进度报告 – 我该怎么做?

我选择这种方法的原因是,后台工作者是这样我可以并行地按顺序启动每个数据库任务。 除此之外,我认为使用TPL可能会很有趣..但是,因为我找不到任何具体的例子,我在下面做了什么(多个任务)我觉得把它放在这里得到它可能会很好答案,希望成为其他人的榜样。

谢谢!

码:

// Disable buttons and start the spinner btnSearch.Enabled = btnClear.Enabled = false; searchSpinner.Active = searchSpinner.Visible = true; // Setup scheduler TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext(); // Start the tasks Task.Factory.ContinueWhenAll( // Define the search tasks that return List new [] { Task.Factory.StartNew<List>(Search1), Task.Factory.StartNew<List>(Search2) }, // Process the return results (taskResults) => { // Create a holding list List documents = new List(); // Iterate through the results and add them to the holding list foreach (var item in taskResults) { documents.AddRange(item.Result); } // Assign the document list to the grid grid.DataSource = documents; // Re-enable the search buttons btnSearch.Enabled = btnClear.Enabled = true; // End the spinner searchSpinner.Active = searchSpinner.Visible = false; }, CancellationToken.None, TaskContinuationOptions.None, scheduler ); 

问:我这样做是对的吗? 有没有更好的办法 ?

是的,这是处理这种情况的好方法。 就个人而言,我会考虑将UI的禁用/启用重构为一个单独的方法,但除此之外,这似乎是非常合理的。

问:我如何为此添加取消/exception检查?

您可以将CancellationToken传递给您的方法,让他们检查并在请求取消时抛出。

您可以处理从taskResults获取结果的exception。 这一行:

  documents.AddRange(item.Result); 

如果在操作期间发生exception或取消,则抛出exception(作为AggregateExceptionOperationCanceledException )。

问:如果我需要添加进度报告 – 我该怎么做?

最简单的方法是将调度程序传递给您的方法。 完成后,您可以使用它来安排在UI线程上更新的任务 – 即: Task.Factory.StartNew并指定了TaskScheduler


但是,因为我找不到任何我在下面做的具体例子(多个任务)

仅供参考 – 我在TPL系列的第18部分中有多个任务的样本 。

有关最佳实践,请阅读基于任务的异步模式文档 。 它包括有关基于Task的API的取消支持和进度通知的建议。

您还可以从Async CTP中的async / await关键字中受益; 它们大大简化了任务延续。