4

I have console application and code as below,

My problem is before ContinueWith task finish, the console application ends, it does not waits the continueWith to finish, please advise.

Please let me know what I am missing or incorrect.

var task1 = Task<bool>.Factory.StartNew(() => DoProcess());

task1 .ContinueWith(
     t1 => updateSuccess(),
       TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);

task1 .ContinueWith(
     t => updateFault(),
     TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);

task1.Wait();
Keshavdas M
  • 674
  • 2
  • 7
  • 25

3 Answers3

8

You have to wait on the task to complete from the main thread. Simplified it'll look like

var task1 = Task<bool>.Factory.StartNew(() => DoProcess());

successContinuation = task1 .ContinueWith(t1 => updateSuccess(),
                                          TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously)
failureContinuation = task1 .ContinueWith( t => updateFault(),
                                          TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);

Task.WaitAny(successContinuation, failureContinuation);

I think you're not realizing that you're creating a task that will (actually just may) execute in a different thread. The moment you start your task you have two different threads of execution the main thread, which will continue to run, and your task. If you want your main thread (your console application) to wait for the task to finish, you have to manually specify it.

Jorge Córdoba
  • 51,063
  • 11
  • 80
  • 130
  • If you see my code above it also has a condition to execute or not to execute based on "TaskContinuationOptions" so if one of the continueWith executes then other fails with Task canceled error. Please advise how to avoid this. – Keshavdas M Jun 02 '14 at 05:15
  • See edited response. Since continuation are exclusive (it will either fault or not, so only one of the resulting tasks is going to run) you wait for any of them to complete. – Jorge Córdoba Jun 02 '14 at 09:01
1

Jorge's solution is not working when an exception is thrown :

var task = new Task(() =>
    {
        Console.WriteLine("My task...");
        throw new Exception();
    });

task.Start();

var taskNotOnFaulted = task.ContinueWith(t =>
{
    Thread.Sleep(1000);
    Console.WriteLine("NotOnFaulted");
}, TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
var taskOnlyOnFaulted = task.ContinueWith(t =>
{
    Thread.Sleep(1000);
    Console.Write("OnlyOnFaulted");
}, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);

Task.WaitAny(taskNotOnFaulted, taskOnlyOnFaulted);

Console.WriteLine("Finished");

The output is :

My task...
Finished
OnlyOnFaulted

This is because the taskNotOnFaulted get a Cancelled status when the exception is thrown, whereas it keeps a WaitingForActivation status when no exception is thrown.

So you have to replace :

Task.WaitAny(taskNotOnFaulted, taskOnlyOnFaulted);

by

if (task.IsFaulted)
    taskOnlyOnFaulted.Wait();
else
    taskNotOnFaulted.Wait();
TheOnlyMaX
  • 19
  • 2
0

I tried another solution that worked for me :

try {
    taskNotOnFaulted.Wait();
} catch {
    taskOnlyOnFaulted.Wait();
}
NwP_290
  • 9
  • 2