假设我们有以下方法:
private async Task<string> Foo(string parameter)
{
// Some code to convert source parameter
string convertedParameter = //value;
CallResult callResult;
try
{
var integerResult = await LoadInformationAsync(convertedParameter);
if (integerResult > 0)
{
callResult = // Some logic to analyse integerResult and generate CallResult object
}
else
{
callResult = // Some logic to analyse integerResult and generate CallResult object
}
}
catch (Exception ex)
{
callResult = CallResult.Default; // some default value if call failed
}
var stringResult = // some logic to convert callResult instance to some another string result;
return stringResult; //Finally return the result
}
我们不要深入细节。主要的是这个方法包含一些业务逻辑和调用(假设3d方)方法LoadInformationAsync
,这是等待的。
这些评论的背后可能是大量的业务逻辑,所以,我认为,每个人都会同意将逻辑拆分为单独的方法(甚至是类)肯定是好的。
因此,LoadInformationAsync
方法的核心调用将更深入调用堆栈。像这样:
private async Task<string> Foo(string parameter)
{
// Some code to convert source parameter
string convertedParameter = //value;
CallResult callResult = await MakeSafeCall(convertedParameter);
var stringResult = // some logic to convert callResult instance to some another string result;
return stringResult; //Finally return the result
}
private async Task<CallResult> MakeSafeCall(string parameter)
{
try
{
var integerResult = await LoadInformationAsync(convertedParameter);
if (integerResult > 0)
{
return callResult = // Some logic to analyse integerResult and generate CallResult object
}
else
{
return callResult = // Some logic to analyse integerResult and generate CallResult object
}
}
catch (Exception ex)
{
return CallResult.Default;
}
}
因此,我们的代码略胜一筹。 F.E.是某些类/方法可能想要调用方法MakeSafeCall
来尝试/ catch。
但我们现在有什么?我们有一个额外的异步方法需要等待。并且每对async / await都会为捕获上下文的状态机等提供支持。好吧,我们可以处理这个开销,但是如果我们有更复杂的逻辑(通常我们真的这么做)会迫使我们将根方法分成更小的和平。我们的异步/等待对数将增加。而且似乎不是很好。
所以问题是:在这种情况下使用async / await的好方法是什么?
答案 0 :(得分:3)
我认为Stephan Toub在他的文章 Async Performance: Understanding the Costs of Async and Await
中对你的问题有一个很好的答案异步方法是一种强大的生产力工具,使您能够 更轻松地编写可扩展和响应的库和应用程序。 但重要的是要记住,异步性不是一个 单个操作的性能优化。 同步操作并使其异步将始终如一 降低一个操作的性能,因为它仍然需要 完成同步操作所做的一切,但现在用 其他限制和考虑因素。你关心的一个原因 那么,异步性就是在总体上的表现:你的如何 当您以异步方式编写所有内容时,整个系统会执行 您可以重叠I / O并实现更好的系统利用率 仅在实际需要时才消耗宝贵的资源 执行。 .NET提供的异步方法实现 框架已经过很好的优化,并且通常最终会提供良好的或 比编写良好的异步实现更好的性能 使用现有模式和卷更多代码。任何时候你 计划从现在开始在.NET Framework中开发异步代码 在,异步方法应该是您的首选工具。
最重要的是,不要过早优化。如果您对代码进行基准测试并发现async
方法是一个瓶颈,请查看它背后的内容以及如何编写代码以提高性能。但请记住,.NET框架团队在实现async-await时会考虑到这一点,您可以在详细信息中看到,例如使AsyncTaskMethodBuilder
成为结构而不是减少GC压力的类等。
我建议您仔细阅读stephans文章,以便更好地了解框架所带来的成本/优化。
答案 1 :(得分:1)
开销实际上可以忽略不计,特别是当它被很多业务逻辑包围时。当有以下内容时,您可以尝试删除多余的async-await
来电:
转到:
async Task Wait()
{
await Task.Delay(1000);
}
要:
Task Wait()
{
return Task.Delay(1000);
}
但不要对此感到困惑。你可能永远不会达到实际上是你的瓶颈的地步。如果你这样做,还有更多的.Net功能需要用,例如yield
(以及大多数带有它的LINQ)或者甚至是lambda表达式。