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?
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With