18

为什么我们需要Task.ContinueWith()方法。我们不能只在任务主体中编写那个“延续代码”吗?

4

3 回答 3

10

Sasha Goldshtein 的回答是正确的。在某些情况下,您的“继续”组合代码无法直接访问,甚至无法设置任务的执行方法。例如,想要聚合任务的可插拔系统。

但是,还有另一个原因可能适用。粒度

考虑可能引发使用TaskCreationOptions.LongRunning的要求。在一个有数百个进程正在被调度、​​执行和完成的并行系统中,任务调度器在调度任务时正在努力提高处理器的效率。

如果您处于可以将任务分解为细粒度的子任务并将它们链接起来的情况,您将不再需要使用TaskCreationOptions.LongRunning。简单来说,这会表现得更好,因为调度 100 个小任务同时完成,比在只有 4 个内核可用的环境中调度 10 个大任务来完成同样的任务更容易。请记住,不能保证链式任务在其先行之后立即开始。

这是一个有趣的问题,只有当您想要一个可扩展的系统时才会成为一个问题。

如果你问我,你应该尽可能使用 ContinueWith() ,因为它有助于你的应用程序扩展。

于 2012-01-16T10:00:26.830 回答
9

有时您从外部收到一个任务,并希望将您的延续链接到它。还有一些方法可以在没有操作的情况下创建任务(例如,使用 TaskCompletionSource)。

于 2011-06-24T10:36:07.380 回答
5

任务延续允许您使用任务链,链中的每个任务后面跟着另一个任务

同样在方法中,您可以在目标完成或发生错误时异步Task.ContinueWith检查TaskTaskContinuationOptionsTask

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()
);

更多信息请看这里

于 2011-06-24T10:56:56.503 回答