How to await until Task.ContinueWith inner task fi

2019-02-17 05:46发布

问题:

Take a look at this code:

    private async Task InnerTask(bool outerTaskResult)
    {
        Console.WriteLine("2");
        await Task.Factory.StartNew(() => Thread.Sleep(10000));
        Console.WriteLine("3");
    }

    private async void Button2_Click(object sender, RoutedEventArgs e)
    {
        var task = Task.FromResult(false);
        Task<Task> aggregatedTask = task.ContinueWith(task1 => InnerTask(task1.Result));
        Console.WriteLine("1");
        await aggregatedTask;
        Console.WriteLine("4");
    }

The desired output is:

1
2
3
4

But I get:

1
2
4
3

This probably has something to do with InnerTask being executed on a different thread.

I'm using ContinueWith because the tasks in the original code are dynamically created and queued this way.

Using .Wait() method (see below) works, but I think it's a bad idea, as the method is blocking.

task.ContinueWith(task1 => InnerTask(task1.Result).Wait())

What's the correct approach here?

回答1:

You can use TaskExtensions.Unwrap() (which is an extension method on Task<Task>) to unwrap the outter task and retrieve the inner one:

private async void Button2_Click(object sender, RoutedEventArgs e)
{
    var task = Task.FromResult(false);
    Task aggregatedTask = task.ContinueWith(task1 => InnerTask(task1.Result)).Unwrap();
    Console.WriteLine("1");
    await aggregatedTask;
    Console.WriteLine("4");
}

Note that to simplify this entire thing, instead of ContinueWith style continuation you can await on your tasks:

private async void Button2_Click(object sender, RoutedEventArgs e)
{
    var task = Task.FromResult(false);

    Console.WriteLine("1");

    var result = await task;
    await InnerTask(result);

    Console.WriteLine("4");
}