我正在为POC构建我的dotnet core webapi服务,我担心为前进的其他拱门/开发人员设置适当的指导。
"相同"方法签名的变化很少
- public dynamic get(字符串name = _defaultName(
- public iRinctionResult get(字符串name = _defaultName(
- public async任务get(字符串name = _defaultName(
独自一人讨论为什么我要使用动态而不是自定义类型,我试图了解差异和收益。
请更正我的(MIS(理解:
- 无法控制HTTP响应,标题,代码等 - 在成功或失败的情况下,全部由框架设置,运行时工具可见返回类型
- 更好地控制HTTP响应,但是在执行该方法时它将绑定威胁,没有输出数据类型的定义
- 更好地控制HTTP响应,在执行该方法时不会绑定威胁,但会旋转另一个线程来计算结果,并且没有针对输出类型的定义
第三选项的实现将如下:
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方法和产生的有点奇怪的代码。
- 无法控制HTTP响应,标题,代码等 - 在成功或失败的情况下,全部由框架设置,运行时工具可见返回类型
您不必使用动态,如果您需要从操作中返回任意响应,则可以使用
public IActionResult Get(string name = _defaultName)
{
// or any other method which accepts a response object)
return Ok(someModel);
}
- 更好地控制HTTP响应,但是在执行该方法时它将绑定线程,没有输出数据类型的定义
在操作的过程中,请求线程将保持在遵守。但是,如果您不使用任何异步操作(DB访问,网络连接到另一个网站/WebService或将文件读取到数据库(,则可以使用它。
// Here no async operations are called, so Task is not necessary
public IActionResult Index(string name = _defaultName)
{
if(!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return Ok();
}
对于异步操作,您应该使用Task<IActionResult>
。
- 更好地控制http响应,在执行该方法时不会绑定线程,但会旋转另一个线程以计算结果,并且没有针对输出类型的定义
这个假设是错误的。单独使用真正的ASYNC操作(I/O操作,例如从文件系统中阅读,网络连接或数据库访问(将 not Spawn 一个新线程。该操作将启动,线程返回到线程池。
没有新线程将启动。当异步操作完成后,将从线程池中取出一个线程,然后操作继续。
// No extra thread is called and the request thread is only
// used in between "await" calls
public async Task<IActionResult> Get(string name = _defaultName)
{
var result = await GetResultFromDatabase();
return Ok(someModel);
}
请阅读异步编程:在Stephen Cleary上的MSDN上的ASP.NET文章中,异步/等待。它是关于ASP.NET MVC 5(旧的WebStack,而不是重写ASP.NET Core(,但该原理仍然适用于ASP.NET Core。
如果您拥有 CPU绑定操作(计算一些复杂的数学等(,则请勿启动新的线程。这将使ASP.NET Core如何管理线程池的方式混乱,您将一无所获,但仍将拥有上下文开关的开销,因此它将降低您的性能而不是提高其性能。
对于CPU绑定的操作,只需runt hem 同步在请求线程上。
public IActionResult Get(string name = _defaultName)
{
// Don't await or run CPU intensive stuff via Task.Run
var result = SomeCpuIntensiveOperation();
return Ok(result);
}
您也可以混合CPU绑定和异步操作
public async Task<IActionResult> Get(string name = _defaultName)
{
// runs async, no extra thread
var valueFromDb = await GetValueFromDb();
// Don't await or run CPU intensive stuff via Task.Run
// runs sync, on request thread
var result = SomeCpuIntensiveOperation(valueFromDb);
return Ok(result);
}
我想知道没有这样的下游异步依赖项是否有意义,可以追求异步WebAPI方法和产生的有点奇怪的代码。
这是您决定的,基于有关您的第三个假设的新知识
通常,与线程池中可用线程的请求更多时,异步缩放得更好。但是,大多数小规模的应用程序永远不会达到这种状态,尤其是当它是学习练习或概念证明时。
除非您有一个高流量的网站,该网站处理100或1000秒的请求每秒。