Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task continuations always run even when specifying TaskContinuationOptions

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?

like image 375
corvuscorax Avatar asked Jan 19 '13 12:01

corvuscorax


1 Answers

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);
like image 153
Jon Skeet Avatar answered Oct 11 '22 20:10

Jon Skeet