如何等待Task.ContinueWith内部任务完成

时间:2015-02-18 15:14:40

标签: c# .net task-parallel-library async-await task

看看这段代码:

    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");
    }

所需的输出是:

1
2
3
4

但我明白了:

1
2
4
3

这可能与在不同线程上执行的InnerTask有关。

我正在使用ContinueWith,因为原始代码中的任务是以这种方式动态创建和排队的。

使用 .Wait()方法(见下文)有效,但我认为这是一个坏主意,因为该方法正在阻止。

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

这里有什么正确的方法?

1 个答案:

答案 0 :(得分:9)

您可以使用TaskExtensions.Unwrap()(这是Task<Task>上的扩展方法)来解包外部任务并检索内部任务:

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");
}

请注意,为了简化这一切,您可以ContinueWith代替await样式延续,而不是

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");
}