c# - Excessive use of async await?
问题描述
I'm wondering if I use async
and await
to excessively in my code and if there are (performance) penalties in doing so?
What I often do:
static void Main()
{
var result = Task<int>.Run (()=> S1Async(1)).Result;
Console.WriteLine(result);
}
static async Task<int> WrapperAsync(Func<int, Task<int>> func) => await func(2);
static async Task<int> S1Async(int x) => await WrapperAsync(async t=> await S2Async(x * t));
static async Task<int> S2Async(int x) => await WrapperAsync(async t=> await S3Async(x * t));
static async Task<int> S3Async(int x) => await WrapperAsync(async t=> await S4Async(x * t));
static async Task<int> S4Async(int x) => await Task.FromResult(x * 10);
I think the async-awaits can be skipped and that this code is similar:
static void Main()
{
var result = Task<int>.Run(() => S1Async(1)).Result;
Console.WriteLine(result);
}
static Task<int> WrapperAsync(Func<int, Task<int>> func) => func(2);
static Task<int> S1Async(int x) => WrapperAsync(t => S2Async(x * t));
static Task<int> S2Async(int x) => WrapperAsync(t => S3Async(x * t));
static Task<int> S3Async(int x) => WrapperAsync(t => S4Async(x * t));
static Task<int> S4Async(int x) => Task.FromResult(x * 10);
When tasks are nested with just one task per level, is it safe to skip async/await?
Both code-samples gives the same result in LinqPad, so I assume they are similiar, but maybe there are side-effects I should be aware of?
解决方案
简短的回答是:是的,在这种情况下你可以跳过它们,是的,有性能损失。
当您的方法所做的只是await
一次并立即返回时,如下所示:
async Task FooAsync()
{
/* ... */
await BarAsync();
}
那么它几乎相当于写:
Task FooAsync()
{
/* ... */
return BarAsync();
}
的意思async
是(从 的角度来看FooAsync
):好吧,操作BarAsync
可能需要一段时间才能完成,所以如果我们得到一个未完成Task
的结果,让我保存我当前的状态并将控制流返回给我的调用者。一旦Task
完成,我想恢复状态并继续我一直在做的事情。
在这种情况下,很明显在完成后不会执行任何额外的工作BarAsync
Task
,因此您可以将其返回Task
给调用者,因为有效地FooAsync
完成了完全相同的时刻Task
。无需保存任何状态或安排继续。
当我们谈论单个调用时,这样做的开销并不大,但是如果您多次调用此方法,您可能会感觉到影响。async
编译器必须在您声明您的方法的那一刻设置整个基础架构async
- 状态机,继续调度,整个包。所以作为一般规则:如果你可以简化你的方法而不是async
简单地返回另一个Task
,那么这样做是值得的。
附带说明:您当然不需要将S1Async
调用包装到 aTask.Run
中,并且您不必在Main
自 C# 7.1 以来同步阻塞。你可以写:
static async Task Main()
{
var result = await S1Async(1);
Console.WriteLine(result);
}
推荐阅读
- python - 如何检索xml文件的doctype
- sql - 使用SQL返回完整的转换表
- sql - 从别名插入数据
- qnx - 如何在 qnx 6.4.1 中安装 rsync?
- reactjs - useCallback 在 ReactJS 中包装一个简单的函数
- .net - WebView2:我必须安装 Microsoft.Web.WebView2.DevToolsProtocolExtension 吗?
- spring-boot - Spring Boot 谷歌搜索结果
- javascript - 在 react js 中进行单元测试时,有没有办法改变 props 值?
- apache - 服务器证书不包含与 apache 中的服务器名称匹配的 ID
- tableau-api - 如何在 Tableau 计算字段中使用 case 语句计算平均值?