Task continuations always run even when specifying

2019-06-24 02:58发布

I want to run some code when an async task completes successfully.

From reading documentation and examples on the web, I thought I could use Task.ContinueWith and specify TaskContinuationOptions.OnlyOnRanToCompletion.

However, this doesn't behave as I expected.

The following code is a console program, created in 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();
        }
    }
}

when run, I get the output:

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

which is very surprising (at least to me). Why are both continuations scheduled?

I get the same behavior if I throw an exception in jobTask, but the output is now:

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

So the framework clearly knows the status of the task, but why are both continuations still scheduled?

1条回答
做个烂人
2楼-- · 2019-06-24 03:23

I think the problem is that you're accidentally calling this overload

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

What you want is this overload:

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

You just need to change your lambda expressions to use a single parameter:

Task.ContinueWith(task => Console.WriteLine(...),
    TaskContinuationOptions.OnlyOnRanToCompletion);
查看更多
登录 后发表回答