2016-03-08 237 views
1

方法1:这两种任务方法的行为有什么不同?

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

方法2:

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

请帮我找的区别:

await FirstDelayAsync(); 
await SecondDelayAsync(); 

感谢。

+5

一个叫做'First',另一个叫'Second'。一个是“异步”,另一个不是。这不是http://puzzling.stackexchange.com。你真的想知道什么?你的问题[如何异步调用同步方法](http://stackoverflow.com/questions/18830397/awaiting-a-non-async-method)? – CodeCaster

+1

@CodeCaster:这是一个合理的问题。即使两者之间没有功能上的差异(事实并非如此),OP的要求也是合理的。但是,这可能是一个重复的问题。 – Douglas

+0

为了DRY的利益标记为重复。尽管它的标题,链接的问题和它接受的答案主要讨论'Task.Delay'的情况,而不是'Task.Run'。 – Douglas

回答

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

0

功能上,这两种方法没有区别。他们的工作是一样的。

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

对于类似于你所拥有的简单例子,第二种方法是首选,因为第一种方法创建一个状态机来处理异步逻辑。对于复杂的异步方法,这样的状态机肯定是需要的,但对于这种简单的情况并不需要。

相关问题