在 C# 不同层级的架构中使用 await 的异步任务

32 浏览
0 Comments

在 C# 不同层级的架构中使用 await 的异步任务

最近我一直在烦恼在哪里应该使用await,哪里不需要。

我有一个Repository类用来从数据库中获取数据,如果使用EntityFramework,则代码如下:

public async Task<List> GetAsync()
{
  return await context.Set().ToListAsync();
}


使用者如下:

var data = await GetAsync();

最高层级上,我也在等待这个方法。我是否应该只在这些方法中使用其中一个await呢?每次使用await会对资源造成性能损失并创建新的线程吗?

我已经查看了评论中列出的问题,但它们并未涉及性能问题,只是说你可以这样做。我想知道最佳实践以及为什么要/不要这样做。

admin 更改状态以发布 2023年5月19日
0
0 Comments
  • Async performance can be optimized by limiting the number of threads generated or by batching calls
  • In case of CPU-bound processing, Async can also help by allowing multiple tasks to run concurrently and not blocking the main thread of execution
  • But it's important to note that using Async excessively or inappropriately can actually hurt performance and increase memory usage
  • Therefore, it's important to measure the performance impact of Async and optimize it accordingly
  • 在纯库调用中,当异步由线程池启动并且分派线程不同于接收线程,且调用不需要重新进入相同的上下文时,应使用ConfigureAwait(false),这意味着它不会等待重新进入原始上下文,这是一种性能提升
  • 就像await一样,跨整个链,从入口到结束使用ConfigureAwait(false)是有意义的。这仅适用于那些在很大程度上依赖线程池的库
  • 基于CPU的异步处理,您可以将事物放在后台处理,在当前线程需要响应的情况下,主要是在Ui中,如WPF
  • 各种系统, 特别是非 MS 框架,如node js,具有异步处理作为基本原则,并且接收端的数据库服务器集群已调整为接收和处理数百万个调用
  • B2C调用,每个请求都应该是轻量级且具有有限的有效负载

编辑1:

就在特定情况下,如这里所列出的,ToListAsync默认是异步的,因此在这种情况下,您可以跳过异步等待,如多个评论中所列出的那样,但是请注意,在一般情况下这可能不是一个很好的策略,因为收益很小,而错误使用的负面影响可能很大,请查看 Stepehen Cleay 的文章进行审查

0
0 Comments

我想补充一点。

有一些async方法在其中没有使用async/await关键词的必要。 正确检测此类误用非常重要,因为添加async修饰符的代价不菲。

例如,您的示例中不需要使用async/await关键词。

public Task> GetAsync()
{
  return context.Set().ToListAsync();
}

然后:

var data = await GetAsync();

就足够了。 在这种情况下,您返回了Task>,然后您在直接处理对象的位置等待它。

我建议安装async await helper

0