即使指定了TaskContinuationOptions,任务延续也始终运行

本文关键字:延续 运行 任务 TaskContinuationOptions | 更新日期: 2023-09-27 17:54:38

我想在异步任务成功完成时运行一些代码。

从阅读文档和示例在网络上,我认为我可以使用Task.ContinueWith和指定TaskContinuationOptions.OnlyOnRanToCompletion

然而,这并不像我所期望的那样。

下面的代码是一个控制台程序,在Visual Studio 2012, .Net 4.5中创建:

using System;
using System.Threading.Tasks;
namespace TaskContinueTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var jobTask = Task.Factory.StartNew(() => { });
            jobTask.ContinueWith((task, options) =>
            {
                Console.WriteLine("Completed handler. Task status is {0}", task.Status);
            }, TaskContinuationOptions.OnlyOnRanToCompletion);
            jobTask.ContinueWith((task, options) =>
            {
                Console.WriteLine("Faulted handler. Task status is {0}", task.Status);
            }, TaskContinuationOptions.OnlyOnFaulted);
            Console.ReadLine();
        }
    }
}
当运行

时,我得到输出:

Completed handler. Task status is RanToCompletion
Faulted handler. Task status is RanToCompletion

这是非常令人惊讶的(至少对我来说)。为什么要安排两个延续?

如果我在jobTask中抛出异常,我会得到相同的行为,但现在输出是:

Completed handler. Task status is Faulted
Faulted handler. Task status is Faulted

所以框架清楚地知道任务的状态,但是为什么两个延续仍然被调度?

即使指定了TaskContinuationOptions,任务延续也始终运行

我认为问题是你不小心调用了这个重载

public Task ContinueWith(
    Action<Task, Object> continuationAction,
    Object state
)

你想要的是这个重载:

public Task ContinueWith(
    Action<Task> continuationAction,
    TaskContinuationOptions continuationOptions
)

你只需要改变你的lambda表达式使用一个参数:

Task.ContinueWith(task => Console.WriteLine(...),
    TaskContinuationOptions.OnlyOnRanToCompletion);