简体   繁体   中英

What's the difference between these three Task Continuations?

I have these two scenarios, but I don't understand why things are happening as they do:

    static void Main(string[] args)
    {
        Console.WriteLine("***Starting T1");
        //run two tasks sequentially
        Task t = FirstTask().ContinueWith(_ => SecondTask(), TaskContinuationOptions.OnlyOnRanToCompletion);
        //register succeded and faulted continuations
        t.ContinueWith(_ => Completion(), TaskContinuationOptions.OnlyOnRanToCompletion);
        t.ContinueWith(_ => Faulted(), TaskContinuationOptions.OnlyOnFaulted);
        Console.ReadLine();
        Console.WriteLine("***Starting T2");
        Task t2 = FirstTask().ContinueWith(_ => FaultTask(), TaskContinuationOptions.OnlyOnRanToCompletion);
        t2.ContinueWith(_ => Completion(), TaskContinuationOptions.OnlyOnRanToCompletion);
        t2.ContinueWith(_ => Faulted(), TaskContinuationOptions.OnlyOnFaulted);
        Console.ReadLine();
        Console.WriteLine("***Starting T3");
        Task t3 = FirstTask().ContinueWith(ant => ant.ContinueWith(_ => FaultTask(), TaskContinuationOptions.OnlyOnRanToCompletion));
        t3.ContinueWith(_ => Completion(), TaskContinuationOptions.OnlyOnRanToCompletion);
        t3.ContinueWith(_ => Faulted(), TaskContinuationOptions.OnlyOnFaulted);
        Console.ReadLine();
    }

    private static Task FirstTask()
    {
        return Task.Run(() =>
        {
            Console.WriteLine("Task 1");
            Thread.Sleep(1000);
        });
    }

    private static Task SecondTask()
    {
        return Task.Run(() =>
        {
            Console.WriteLine("Task 2");
            Thread.Sleep(1000);
        });
    }

    private static Task FaultTask()
    {
        return Task.Run(() =>
        {
            Console.WriteLine("Throw...");
            Thread.Sleep(1000);
            throw new ArgumentException();
        });
    }

    private static void Completion()
    {
        Console.WriteLine("Complete");
    }

    private static void Faulted()
    {
        Console.WriteLine("Faulted");
    }

In case 1, things are ran as expected. However, if the Sleep() in FirstTask() is removed, there is no guarantee the tasks are run in order.

In case 2, The Faulted() handler is not run. I would expect this to occur since there is an unhandled exception.

In case 3, the exception is thrown after the Complete() handler is run. I am confused as to why this ordering has occurred.

Basically I want to be able to chain as many tasks as I want and for them to run in order after the previous one finished. Once I have created the chain, I will then show a wait form and register continuations for OnlyOnRanToCompletion , OnlyOnCancelled , OnlyOnFaulted into the final task (read: after all have finished) to close the form - displaying success or error.

Is this where MSDN is referring to those options that are not available for multi task continuations?

Your return type on t and t2 are Task<Task> not just a Task. T3 is a Task<Task<Task>> . To get the desired behavior, you should be able to Unwrap the tasks which will give you a task that represents the entire operation (read the docs for more info):

Console.WriteLine("***Starting T1");
//run two tasks sequentially
Task<Task> t = FirstTask().ContinueWith(_ => SecondTask(), TaskContinuationOptions.OnlyOnRanToCompletion);

//register succeded and faulted continuations
t.Unwrap().ContinueWith(_ => Completion(), TaskContinuationOptions.OnlyOnRanToCompletion);
t.Unwrap().ContinueWith(_ => Faulted(), TaskContinuationOptions.OnlyOnFaulted);

Console.ReadLine();
Console.WriteLine("***Starting T2");

Task<Task> t2 = FirstTask().ContinueWith(_ => FaultTask(), TaskContinuationOptions.OnlyOnRanToCompletion);
t2.Unwrap().ContinueWith(_ => Completion(), TaskContinuationOptions.OnlyOnRanToCompletion);
t2.Unwrap().ContinueWith(_ => Faulted(), TaskContinuationOptions.OnlyOnFaulted);
Console.ReadLine();

I would recommend looking into using the async/await pattern where possible, as it makes dealing with tasks like these much easier.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM