await与Task.ContinueWith()的区别

在代码库里看到不少Task.ContinueWith()的代码,查了下语法,没太理解下面两种写法的区别(借用MSDN的代码):

public static async Task ContinueWithExample()
{
    // Execute the antecedent.
    Task<DayOfWeek> taskA = DayOfWeekAsync();

    // Execute the continuation when the antecedent finishes.
    await taskA.ContinueWith(antecedent => Console.WriteLine("Today is {0}.", antecedent.Result));
}
public static async Task AwaitExample()
{
    DayOfWeek dayOfWeek = await DayOfWeekAsync();
    Console.WriteLine("Today is {0}.", dayOfWeek);
}

public static async Task<DayOfWeek> DayOfWeekAsync()
{
    Console.WriteLine("Enter DayOfWeekAsync()");
    await Task.Delay(500);
    return DateTime.Today.DayOfWeek;
}

await与ContinueWith的区别

标题有些标题党,但实际上await是continuewith的替代者,是一种更先进和简洁的语法。

在第一个Reference中最高回答解释了异步编程的发展流程:

  1. 早期使用多个回调函数,繁琐冗长
  2. C# 4.0之后出现了ContinueWith(),可以将task链式串联起来,看起来更像同步式编程语法
  3. C# 5.0引入了async/await机制,让异步代码更像同步代码,更为简洁。同时,作为后继者让ContinueWith()基本没有太多应用场景了。

所以在代码库中看到许多ContinueWith其实是在C# 4.0时代的陈年老代码,并非最近写出的代码。尴尬的是,许多人并不了解其中原因,还把老代码抄过来使用,相当于放着法拉利不开非要玩富康。

结论

在能用await的地方尽量用await,抛弃Task.ContinueWith()。

References

Why would you want to use continueWith instead of simply appending your continuation code to the end of the background task?

Why you should not use “ContinueWith” in your async code

Chaining Tasks by Using Continuation Tasks

The history of C#