这两种任务方法的行为有何不同?

时间:2016-03-08 11:01:01

标签: c# .net asynchronous

方法1:

private static async Task FirstDelayAsync()
{
    await Task.Delay(1000);
}

方法2:

private static Task SecondDelayAsync()
{
    return Task.Delay(1000);
}

请帮我找出差异:

await FirstDelayAsync();
await SecondDelayAsync();

感谢。

2 个答案:

答案 0 :(得分:4)

两者非常相似。当遇到async方法时,C#编译器将生成状态机,以便返回的Task表示方法的完成。因为你的方法所做的唯一事情是等待另一个异步操作,所以这在功能上几乎等同于直接从内部异步操作返回Task

然而,关于如何抛出同步部分的异常,存在细微差别。在async方法中执行的任何逻辑,包括方法开头的同步部分(在第一个await语句之前),将作为异步操作的一部分进行编译。这意味着前提条件异常将不再同步传递,而是通过返回的Task异步传递:

private static async Task FirstDelayAsync()
{
    if (StateNotValid)
        throw new NotSupportedException();

    await Task.Delay(1000);
}

private static Task SecondDelayAsync()
{
    if (StateNotValid)
        throw new NotSupportedException();

    return Task.Delay(1000);
}

测试上面的代码:

var t1 = FirstDelayAsync();
await t1;                       // exception thrown here

var t2 = SecondDelayAsync();    // exception thrown here
await t2;

如果您在调用它的同一行上等待异步操作,这将没有什么区别。但是,如果你拖延等待,它会有所作为;例如,如果同时启动多个异步操作,然后使用Task.WhenAll

等待它们
var tasks = Enumerable
    .Range(0, 10)
    .Select(i => ProcessAsync(i))
    .ToArray();

await Task.WhenAll(tasks);

在上面的代码片段中,ProcessAsync调用引发的同步异常会阻止后续异步操作甚至被启动,因为异常会立即停止枚举。这通常适用于应该停止整个过程的失败前提条件。

更新:另一个重要的不同之处是,使用await而不使用ConfigureAwait(false)会使您的代码更容易死锁。请参阅this answer

答案 1 :(得分:0)

从功能上讲,这两种方法没有区别。他们的工作方式相同。

asyncawait允许您创建复杂的异步方法,允许您编写看起来像同步代码但实际上是异步的代码。

对于像你这样的简单情况,第二种方法是首选方法,因为第一种方法创建了一个状态机来处理异步逻辑。在复杂的异步方法中肯定需要这样的状态机,但对于这种简单的情况不需要。