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

问题描述 投票:0回答:2

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

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

问:我这样做的方法正确吗?有更好的办法吗
问:我如何添加取消/例外检查?
问:如果我需要添加进度报告 - 我该怎么做?

我选择这种方法而不是后台工作人员的原因是,我可以并行而不是顺序地触发每个数据库任务。除此之外,我认为使用 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<ImageDocument>
  new [] {  
    Task.Factory.StartNew<List<ImageDocument>>(Search1), 
    Task.Factory.StartNew<List<ImageDocument>>(Search2) 
  }, 
  //  Process the return results
  (taskResults) => {
    //  Create a holding list
    List<ImageDocument> documents = new List<ImageDocument>();
    //  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
);
c# winforms multithreading task-parallel-library task
2个回答
2
投票

问:我这样做的方法正确吗?有更好的办法吗

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

问:如何添加取消/例外检查?

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

您可以在从taskResults 获取结果时处理异常。这一行:

  documents.AddRange(item.Result);

如果在操作期间发生异常或取消,则会抛出异常(作为

AggregateException
OperationCanceledException
)。

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

最简单的方法是将调度程序传递到您的方法中。完成此操作后,您可以使用它来安排在 UI 线程上更新的任务 - 即:指定了

Task.Factory.StartNew
TaskScheduler


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

仅供参考 - 我在 TPL 系列的第 18 部分中有处理多个任务的示例


0
投票
有关最佳实践,请阅读

基于任务的异步模式文档。它包括有关取消支持的建议以及基于 Task

 的 API 的进度通知。

您还可以从异步 CTP 中的

async

/
await
 关键字中受益;它们极大地简化了任务的延续。

© www.soinside.com 2019 - 2024. All rights reserved.