kri*_*hna 10 c# async-await asp.net-web-api asp.net-core
我有.NET核心Web API作为服务层.服务层具有所有EF代码.
如果有basecontroller与此代码
protected Task<IActionResult> NewTask(Func<IActionResult> callback)
{
return Task.Factory.StartNew(() =>
{
try
{
return callback();
}
catch (Exception ex)
{
Logger.LogError(ex.ToString());
throw;
}
});
}
Run Code Online (Sandbox Code Playgroud)
在控制器操作中,我将上述方法中的所有调用包装到例如:
[HttpGet("something")]
public async Task<IActionResult> GetSomething(int somethingId)
{
return await NewTask(() =>
{
var result = _somethingService.GetSomething(somethingId);
if (result != null)
return Ok(result);
else
return NotFound("Role not found");
});
}
Run Code Online (Sandbox Code Playgroud)
这是正确的模式,考虑到明天,我可能有多个服务呼叫在行动或拨打其他Web服务.请指教.
Ste*_*ary 21
我希望我的api能够从异步等待事物中获益.以上模式将满足这些需求
不,不是的.在线程池上运行同步工作会给你带来同步和异步代码的缺点,但两者都没有好处.
某些服务有一些使用entityframework核心的crud操作
目前,您的操作方法是我称之为"假异步" - 它看起来是异步的(例如,使用await),但实际上只是在后台线程上运行阻塞代码.在ASP.NET上,您需要真正的异步,这意味着您必须始终保持异步.欲了解更多有关这是为什么在ASP.NET坏了,看到我的前半部分介绍到asyncASP.NET的文章(它主要是用ASP.NET非核心的交易,但第一部分讲的同步和异步请求是有效的任何类型的服务器).
要使这真正异步,您应该从最低级别开始 - 在这种情况下,您的EFCore调用.他们都支持异步.因此,更换API调用像x.FirstOrDefault()用await x.FirstOrDefaultAsync()(与同为所有创建/更新/删除等).
然后允许async/ await从那里自然生长; 编译器会指导你.你最终会得到异步方法somethingService,可以这样使用:
[HttpGet("something")]
public async Task<IActionResult> GetSomething(int somethingId)
{
var result = await _somethingService.GetSomethingAsync(somethingId);
if (result != null)
return Ok(result);
else
return NotFound("Role not found");
}
Run Code Online (Sandbox Code Playgroud)
好的,首先,只有当你想在线程池线程上运行大量的CPU工作时才应该停止使用Task.Factory.StartNew和使用Task.Run.在你的情况下,你根本不需要它.此外,您应该记住,您应该只Task.Run在调用方法时使用,而不是在方法的实现中使用.你可以在这里阅读更多相关信息.
在您的情况下,您真正想要的是在您的服务中进行异步工作(我不确定您甚至需要在您的情况下提供服务)当您实际调用数据库并且您想要使用async/await时不只是在后台线程上运行一些东西.
基本上你的服务应该是这样的(如果你确定你需要服务):
class PeopleService
{
public async Task<Person> GetPersonByIdAsync(int id)
{
Person randomPerson = await DataContext.People.FirstOrDefaultAsync(x => x.Id == id);
return randomPerson;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,您的服务现在会对数据库进行异步调用,这基本上就是您的模式应该是什么.您可以将此应用于所有操作(添加/删除/等..)
使服务异步后,您应该能够轻松地使用操作中的数据.
你的行为应该是这样的:
[HttpGet("something")]
public async Task<IActionResult> GetPerson(int id)
{
var result = await PeopleService.GetPersonByIdAsync(id);
if (result != null)
return Ok(result);
else
return NotFound("Role not found");
}
Run Code Online (Sandbox Code Playgroud)