如果我总是使用以下模式,我开始想知道异步编程:
public async Task<int> MyMethodAsync()
{
return await SomeOtherMethodAsync();
}
或者是否安全并且不会产生任何缺陷,将此代码简化为:
public Task<int> MyMethodAsync()
{
return SomeOtherMethodAsync();
}
我开始通过互联网阅读,但找不到任何答案,所有异步编程都只提到第一种模式。
更新1
基于一些答案,在琐碎的方法中,第二个是正确的。但是如果我按照以下方式扩展和编写方法 - 这仍然与上面的代码有关,只是为了显示SomeOtherMethodAsync
方法中的内容:
public async Task<int> SomeOtherMethodAsync()
{
var result1 = await LongRunningThirdMethod();
var result2 = await LongRunningForthMethod();
return result1 + result2;
}
并将我的第二个示例修改为:
public Task<int> MyMethodAsync()
{
SomeSyncMethod();
SomeOtherSyncCode();
return SomeOtherMethodAsync();
}
答案 0 :(得分:2)
在这种特定情况下,不需要等待开销。
async / await旨在使之前的回调地狱,感觉更像是同步编程。 因为在异步调用之后你没有任何事情要做,所以在这种情况下真的没有必要使用await。
所以你只需要返回异步方法,它甚至仍然有其承诺。
更新1
这两种情况都是正确的。当您执行await / async时,编译器会在场景后面创建一个状态机来处理所有回调,如果您没有使用它,则无需创建一个回调。所以这两个例子都是正确的异步/等待代码。
你可以通过同时等待这两个任务来优化它。
public async Task<int> SomeOtherMethodAsync()
{
var resultTask1 = LongRunningThirdMethod();
var resultTask2 = LongRunningForthMethod();
await Task.WhenAll(resultTask1, resultTask2);
return resultTask1.Result + resultTask2.Result;
}
甚至:
public async Task<int> SomeOtherMethodAsync()
{
var resultTask1 = LongRunningThirdMethod();
var resultTask2 = LongRunningForthMethod();
return await resultTask1 + await resultTask2;
}
请参阅Yuval Itzchakov的另一个选择。 关键是,在这里你开始两个,然后等待他们。在你的例子中你开始一个,等待它完成,然后开始下一个......等等。
答案 1 :(得分:1)
这取决于你想要做什么。
通常,当您只在方法内部进行一次异步调用时,您可以节省自己的状态机开销,只需返回Task
,这将等待调用堆栈的更高位置。
您的第二个示例(更新1)必须等待返回异步操作的两个结果。您可以做的是修改代码,以便使用Task.WhenAll
:
public async Task<int> SomeOtherMethodAsync()
{
int[] results = await Task.WhenAll(LongRunningThirdMethod(), LongRunningForthMethod());
return results.Sum();
}
这样,您就不会按顺序等待每个操作完成。一旦他们都返回,你计算总和。