[英]best practice for using async await in webapi
我有.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;
}
});
}
在控制器操作中,我將上述方法中的所有調用包裝到例如:
[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");
});
}
這是正確的模式,考慮到明天,我可能有多個服務呼叫在行動或撥打其他Web服務。 請指教。
我希望我的api能夠從異步等待事物中獲益。以上模式將滿足這些需求
不,不是的。 在線程池上運行同步工作會給你帶來同步和異步代碼的缺點,但兩者都沒有好處。
某些服務有一些使用entityframework核心的crud操作
目前,您的操作方法是我稱之為“假異步” - 它看起來是異步的(例如,使用await
),但實際上只是在后台線程上運行阻塞代碼。 在ASP.NET上,您需要真正的異步,這意味着您必須始終保持異步。 有關為何在ASP.NET上出現問題的更多信息,請參閱我在ASP.NET上的async
介紹的前半部分(它主要處理ASP.NET非核心,但第一部分討論同步和異步請求是有效的對於任何類型的服務器)。
要使這真正異步,您應該從最低級別開始 - 在這種情況下,您的EFCore調用。 他們都支持異步。 因此,使用await x.FirstOrDefaultAsync()
替換x.FirstOrDefault()
等API調用x.FirstOrDefault()
對於所有創建/更新/刪除等都是相同的)。
然后讓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");
}
好的,首先,你應該停止使用Task.Factory.StartNew
並且只有當你想在線程池線程上運行大量的CPU工作時才使用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;
}
}
正如您所看到的,您的服務現在會對數據庫進行異步調用,這基本上就是您的模式應該是什么。 您可以將此應用於所有操作(添加/刪除/等..)
使服務異步后,您應該能夠輕松地使用操作中的數據。
你的行為應該是這樣的:
[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");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.