我是 TPL(任务并行库)的新手,想知道以下是否是启动 1 个或多个任务、整理结果并将其显示在数据网格中的最有效方法。
问:我这样做的方法正确吗?有更好的办法吗
问:我如何添加取消/例外检查?
问:如果我需要添加进度报告 - 我该怎么做?
我选择这种方法而不是后台工作人员的原因是,我可以并行而不是顺序地触发每个数据库任务。除此之外,我认为使用 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
);
问:我这样做的方法正确吗?有更好的办法吗
是的,这是处理此类情况的好方法。就我个人而言,我会考虑将 UI 的禁用/启用重构为一个单独的方法,但除此之外,这似乎非常合理。
问:如何添加取消/例外检查?
您可以将 CancellationToken 传递给您的方法,让他们检查它并在请求取消时抛出。
您可以在从taskResults 获取结果时处理异常。这一行:
documents.AddRange(item.Result);
如果在操作期间发生异常或取消,则会抛出异常(作为
AggregateException
或 OperationCanceledException
)。
问:如果我需要添加进度报告 - 我该怎么做?
最简单的方法是将调度程序传递到您的方法中。完成此操作后,您可以使用它来安排在 UI 线程上更新的任务 - 即:指定了
Task.Factory.StartNew
的 TaskScheduler
。
但是,因为我找不到我在下面所做的任何具体示例(多个任务)
仅供参考 - 我在 TPL 系列的第 18 部分中有处理多个任务的示例。
基于任务的异步模式文档。它包括有关取消支持的建议以及基于 Task
的 API 的进度通知。您还可以从异步 CTP 中的
async
/
await
关键字中受益;它们极大地简化了任务的延续。