Fel*_*ano 1 asynchronous blocking asp.net-core
假设我们有一个 ASP.NET Core 接收一个字符串作为有效负载,大小为几兆字节。第一种方法实现:
[HttpPost("updateinfos")]
public async Task UpdateInfos()
{
var len = (int)this.Request.ContentLength;
byte[] b = new byte[len];
await this.Request.Body.ReadAsync(b,0,len);
var content = Encoding.UTF8.GetString(b);
.....
}
Run Code Online (Sandbox Code Playgroud)
正文是用 读取的ReadAsync,这很好,因为我们在套接字上有 I/O 内容,并且由于调用本身的性质,异步是免费的。但如果我们仔细观察,就会发现该GetString()方法纯粹是 CPU 的,并且是线性复杂度的阻塞。无论如何,这会以某种方式影响性能,因为其他客户端等待我的字节转换为字符串。GetString()我认为为了避免这种情况,解决方案是在线程池上运行 ,方法是:
[HttpPost("updateinfos")]
public async Task UpdateInfos()
{
var len = (int)this.Request.ContentLength;
byte[] b = new byte[len];
await this.Request.Body.ReadAsync(b,0,len);
var content = await Task.Run(()=>ASCIIEncoding.UTF8.GetString(b));
.....
}
Run Code Online (Sandbox Code Playgroud)
请不要介意现在的返回,函数中还需要做更多的事情。
那么问题来了,第二种方法是不是太过分了?如果是这样,区分什么可以作为阻塞运行以及什么必须移动到另一个线程的边界是什么?
你在那里虐待得很厉害Task.Run。Task.Run用于将工作卸载到不同的线程上并异步等待它完成。所以每次Task.Run调用都会引起线程上下文切换。当然,对于不应该在自己的线程上运行的事情来说,这通常是一个非常糟糕的主意。
诸如此类的事情ASCIIEncoding.UTF8.GetString(b)真的很快。创建和管理封装它的线程所涉及的开销比直接在同一线程上执行它要大得多。
通常,您应该Task.Run仅用于卸载(主要是同步)可以从在其自己的线程上运行中受益的工作。或者在某些情况下,您的工作需要更长的时间,但会阻止当前的执行。
在您的示例中,情况并非如此,因此您应该同步调用这些方法。
如果您确实想减少该代码的工作量,则应该了解如何使流正常工作。您在代码中所做的就是完全读取请求正文流,然后才对其进行处理(尝试将其转换为字符串)。
您可以直接使用StreamReader将流作为字符串读取,而不是分离读取二进制流然后将其转换为字符串的过程。这样,您就可以直接读取请求正文,甚至可以异步读取。因此,根据您之后实际使用它做什么,这可能会更有效。
| 归档时间: |
|
| 查看次数: |
1274 次 |
| 最近记录: |