Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步/等待模式会对次要工作单元造成性能损失吗?_C#_.net_Asynchronous_Async Await - Fatal编程技术网

C# 异步/等待模式会对次要工作单元造成性能损失吗?

C# 异步/等待模式会对次要工作单元造成性能损失吗?,c#,.net,asynchronous,async-await,C#,.net,Asynchronous,Async Await,我正在寻找一些关于“工作负载阈值”的指导,在异步/等待有意义的地方(例如,释放IO完成端口并避免线程不足)与工作单元过于简单/便宜而无法执行之间,同步执行是一个更好的选择 换句话说,当与相对快速/资源廉价的工作单元结合使用时,使用async/await是否会导致性能下降,并且简单地同步执行工作将是首选方法 示例(多功能一体方法,所有异步方法都带有wait): 将一些次要更新保存到数据库 使用ReadAsStreamAsync 使用CopyToAsync 使用FlushAsync 首先,您应该知

我正在寻找一些关于“工作负载阈值”的指导,在异步/等待有意义的地方(例如,释放IO完成端口并避免线程不足)与工作单元过于简单/便宜而无法执行之间,同步执行是一个更好的选择

换句话说,当与相对快速/资源廉价的工作单元结合使用时,使用async/await是否会导致性能下降,并且简单地同步执行工作将是首选方法

示例(多功能一体方法,所有异步方法都带有wait):

  • 将一些次要更新保存到数据库
  • 使用
    ReadAsStreamAsync
  • 使用
    CopyToAsync
  • 使用
    FlushAsync

首先,您应该知道,使用
wait
关键字异步调用方法并不意味着该方法无法同步运行。或者更准确地说:这些方法通常返回
任务
任务
IAsyncOperation
(在Windows运行时),并且当方法返回时,该任务很可能会完成。在这种情况下,开销非常小,因为执行线程将继续运行

至于阈值本身,这取决于您想要做什么以及在哪个环境中运行。这是UI应用程序还是服务器应用程序?您希望异步运行以释放UI,还是希望更好地(即更具可伸缩性)使用服务器线程

对于Windows运行时API,Microsoft使用了50毫秒的阈值,这意味着任何可能需要50毫秒以上才能执行的方法都只能以异步形式提供。这背后的逻辑相当简单:这样做可以让UI线程执行长过程,并且不会被阻塞超过50毫秒。换句话说,UI线程可以运行其他有用的代码,例如每秒渲染20次或更多帧

查尔斯·佩佐尔德写道


对于服务器场景,只要释放线程所做的工作超过释放线程所需的工作,异步运行就变得非常有用。根据我的经验,几乎所有IO都是如此。当然,有些东西看起来像IO,但实际上是从内存缓冲区读取或写入内存缓冲区,但在这种情况下,该方法返回的任务将同步完成。

我建议您不要从计时的角度,而是从I/O-vs-CPU的角度来处理

CPU限制的方法自然是同步的;I/O绑定方法自然是异步的

根据您的示例,我假设您的环境是服务器端的:

  • 将一些次要更新保存到数据库。自然异步:网络(或至少是进程外)通信、争用可能性、磁盘I/O
  • 使用ReadAsStreamAsync读取上传到流的非常小的文件。自然异步:网络通信
  • 使用CopyToAsync将读取流复制到文件流。自然异步:争用的可能性,磁盘I/O
  • 使用FlushAsync刷新写入程序流。自然异步:争用的可能性,磁盘I/O
所有这些都是自然的异步操作,因此它们都应该异步实现。CPU比内存快得惊人,内存比网络或磁盘I/O快得惊人。因此,如果同步实现自然异步方法,将阻塞线程。这还不是世界末日,但是如果线程池被阻塞的时间太长,线程池必须进行补偿,您唯一要“保存”的时间是线程切换时间,这将比任何网络或磁盘I/O可能要短几个数量级

另一个要考虑的是不可预测的延迟,这通常是由于资源争用而发生的。如果另一个进程同时向数据库写入数据,该怎么办?如果文件上传时出现路由问题,需要重新传输数据包,该怎么办?如果在您尝试写入输出文件时磁盘正在进行碎片整理,该怎么办?异步操作有这样一种不可预测的趋势,并且

async
code确保阻塞线程的时间不会比预期的长很多


总之:同步代码用于同步(CPU绑定)工作,异步代码用于异步(I/O绑定)工作。

异步总是比较慢,因为要运行的代码更多(除非没有异步部分),所以不清楚您在寻找什么…@Alexei我正在寻找有关异步/等待之间的“工作负载阈值”(例如,释放IO完成端口并避免线程不足)与工作单元过于简单/便宜而无法执行相比,同步执行是一个更好的选择。我明白了。我担心您必须衡量自己,并找到适合自己的方法。如果不是负载沉重的服务器应用程序,那么您可以使用同步版本(显然不是桌面情况下的主UI线程)…我个人认为,对于服务器来说,如果可能的话,完全异步是更安全的-任何特定的资源往往会在同一时间为所有线程忙碌,并且很快会丢失所有请求线程…绝对存在一些阈值,低于该阈值时,同步执行某些操作会更快,但我认为这些都不符合条件(MemoryStream上的FlusAsync除外)。调度程序可能会产生很大的不同。如果通知发生在线程池线程上,并且需要调度到主线程上,则与直接在线程池线程上处理通知相比,会产生很大的开销。请参阅