【发布时间】:2011-06-24 10:34:46
【问题描述】:
为什么我们需要Task.ContinueWith() 方法。我们不能在任务正文中写那个“延续代码”吗?
【问题讨论】:
标签: c# multithreading parallel-processing task-parallel-library conceptual
为什么我们需要Task.ContinueWith() 方法。我们不能在任务正文中写那个“延续代码”吗?
【问题讨论】:
标签: c# multithreading parallel-processing task-parallel-library conceptual
Sasha Goldshtein 的回答是正确的。在某些情况下,您的“继续”组合代码无法直接访问,甚至无法设置任务的执行方法。例如,想要聚合任务的可插拔系统。
但是,还有另一个原因可能适用。粒度
考虑可能引发使用TaskCreationOptions.LongRunning 的要求。在一个有数百个进程被调度、执行和完成的并行系统中,任务调度器在调度任务时致力于提高处理器的效率。
如果您可以将任务分解为细粒度的子任务并将它们链接起来,则不再需要使用TaskCreationOptions.LongRunning。简单来说,这会表现得更好,因为调度 100 个小任务同时完成比在只有 4 个内核可用的环境中调度 10 个大任务执行相同的任务更容易。请记住,不能保证链式任务在其前面的任务之后立即开始。
这是一个有趣的问题,而且只有在您想要一个可扩展的系统时才会成为一个问题。
如果您问我,您应该尽可能使用 ContinueWith(),因为它有助于您的应用扩展。
【讨论】:
有时您从外部收到一个任务,并希望将您的延续链接到它。还有一些方法可以在没有 Action 的情况下创建任务(例如,使用 TaskCompletionSource)。
【讨论】:
任务延续允许您创建任务链,链中的每个任务都跟在另一个任务之后
同样在Task.ContinueWith方法中,当目标Task完成或发生错误时,您可以异步检查Task和TaskContinuationOptions
Task task = Task.Factory.StartNew
(
() =>
{
//Your action when the task started
}
);
task.ContinueWith
(
_ =>
{
//Your action when the task completed
},
CancellationToken.None,
TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent,
TaskScheduler.FromCurrentSynchronizationContext()
);
task.ContinueWith
(
(t) =>
{
//Action when error occured
Exception exception = null;
if (t.Exception.InnerException != null)
{
exception = t.Exception.InnerException;
}
else
{
exception = t.Exception;
}
//You can use this exception
},
CancellationToken.None,
TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent,
TaskScheduler.FromCurrentSynchronizationContext()
);
更多信息请看here
【讨论】: