我正在为PoC构建我的dotnet核心webapi服务,我担心为其他拱门/开发人员提供正确的指导 .
“相同”方法签名的变化很少
-
public dynamic Get(string name = _defaultName)
-
public IActionResult Get(string name = _defaultName)
-
public async Task Get(string name = _defaultName)
单独讨论为什么我使用动态而不是自定义类型,我试图理解差异和好处 .
请纠正我的(误)理解:
-
无法控制http响应, Headers ,代码等 - 在成功或失败的情况下由框架设置,返回类型对运行时工具可见
-
更好地控制http响应,但它会在执行方法时占用威胁,没有输出数据类型的定义
-
更好地控制http响应,不会在执行方法时绑定威胁,但会分离另一个线程来计算结果,并且没有输出类型的定义
第3个选项的实现如下所示:
public async Task<IActionResult> Get(string name = _defaultName)
{
return await Task.Run(() => {
dynamic response = new System.Dynamic.ExpandoObject();
response.message = $"Hello {name}!";
response.timestamp = DateTime.Now.ToUniversalTime();
if (name.Equals(_defaultName, StringComparison.CurrentCultureIgnoreCase)) {
response.hint = "Add forward slash and your name to the url, e.g.: hostname:port/my name";
}
return Ok(response);
});
}
我理解,对于HttpClient和EntityFramework等异步依赖,异步方法的实现已经存在 .
我想知道如果没有这样的下游异步依赖关系来追求异步webapi方法以及产生一些奇怪的代码是否有意义 .
1 回答
你不应该使用动态,如果你需要从动作中返回任意响应,你可以使用
请求线程将在动作是的持续时间内保持 . 但是,如果您不使用任何异步操作(DB Access,与另一个网站/ Web服务的网络连接或读/写文件到数据库),使用它就可以了 .
对于异步操作,您应该使用
Task<IActionResult>
.这种假设是错误的 . 单独使用Task和真正的异步操作(I / O操作,如从文件系统读取,网络连接或访问数据库)将会成为一个新线程 . 该操作将启动并且线程返回到线程池 .
将启动 No new thread . 当异步操作完成时,将从线程池中获取一个线程并继续操作 .
请阅读Stephen Cleary关于MSDN的Async Programming : Introduction to Async/Await on ASP.NET文章 . 它是关于ASP.NET MVC 5(旧的webstack,而不是重写的ASP.NET Core),但原理仍然适用于ASP.NET Core .
如果你有 CPU bound 操作(计算一些复杂的数学等),那么 do not start a new thread . 这将搞砸ASP.NET Core如何管理线程池,你将什么也得不到,但仍然会有上下文切换的开销,因此它会降低你的性能而不是增加它 .
对于CPU绑定操作,只需在请求线程上删除__2020964_ .
您还可以混合CPU绑定和异步操作
根据您对第三个假设的新知识,这是由您决定的
通常,当您有比线程池中的可用线程更多的请求时,异步会更好地扩展 . 但是大多数小型应用程序从未达到过这种状态,特别是当它是学习练习或概念证明时 .
除非你有一个处理100或1000个请求的高流量网站 per second ,否则你不太可能达到这个限制 .