在Blazor服務器應用程式中,我們似乎被鼓勵盡可能地使用異步功能,而且我大致明白其中的原因。盡管如此,還是希望有人能夠解釋一下使用異步函式時的一般期望,并為我填補一些缺失的知識--我被外面的所有資訊所迷惑,需要一些針對我正在做的事情的具體資訊,以幫助我理解。
我試圖在可能的情況下堅持使用異步,而且在大多數情況下,這樣做是相當容易的,但是當呼叫一些函式時,讓它們成為異步似乎有些矯枉過正(或者說是這樣?在下面的示例中,非異步的 "ValidateEvent "函式正從一個異步函式中被呼叫。
a)從異步函式中正常呼叫它(這似乎違背了異步的意義),例如:"var validationResult = ValidateEvent(objDto);"?
b)使用Task.Run來呼叫它,例如:"await Task.Run(() =>ValidateEvent(objDto));"?
c)將這個簡單的IF/ELSE方法轉換成一個Async函式?
提前感謝任何幫助/建議。
//example async function, that itself calls the other non-async function.
public async Task<Response> AddAsync(ObjDto objDto)
{
//a)正常呼叫?
var validationResult = ValidateEvent(objDto)。
//b) 使用Task.Run呼叫它?
var validationResult = await Task.Run(() =>ValidateEvent(objDto) )。
//在這里異步地做一些事情。
...
await _db.AddAsync(objDto)。
await _db.SaveChangesAsync()。
...
驗證功能:
c) 我是否真的應該將其轉換為異步,因為它只是一系列的 "IFs和ELSEs"(異步轉換將在下面進一步進行)
/Non-Async version
public ResponseObj ValidateEvent(ObjDto obj)。
{
ResponseObj responseObj = new()。
string stringErrors = "";
//If not full day, check that end date is not before start date.
if (!obj.IsFullDay)
{
if (obj.EndTime < obj.StartTime)
stringErrors = ("End date cannot be before the start date<br />")。
}
...其他代碼被移除 for簡潔性
if (string.IsNullOrEmpty(stringErrors) //Success。
{
responseObj.Status = responseObj.Success。
}
else //errors { responseObj.Status = responseObj.Success; }
{
responseObj.Status = responseObj.Error;
responseObj.Message = stringErrors。
}
return responseObj;
}
//Example Async conversion - 是否值得使用Task.Run進行轉換?
/Async conversion
public async Task<ResponseObj> ValidateEvent(ObjDto obj)
{
ResponseObj responseObj = new()。
string stringErrors = ""/span>;
await Task.Run(() =>
{
//If not full day, check that end date is not before start date[/span].
if (!obj.IsFullDay)
{
if (obj.EndTime < obj.StartTime)
stringErrors = ("End date cannot be before the start date<br />")。
}
if (string.IsNullOrEmpty(stringErrors)) //Success (string.IsNullOrEmpty(stringErrors)
{
responseObj.Status = responseObj.Success。
}
else //errors ?
{
responseObj.Status = responseObj.Error;
responseObj.Message = stringErrors。
}
}
);
return responseObj;
另外,提前感謝任何幫助/建議,以了解一般情況下的最佳方式。
uj5u.com熱心網友回復:
a) 從Async函式中正常呼叫它......
是的
... (這似乎違背了異步的意義)
不是的。
uj5u.com熱心網友回復:
這取決于
ValidateEvent方法的作用。
如果它所做的作業是微不足道的,不會隨著時間的推移而增加,就像你的例子所建議的那樣,那么從異步的
AddAsync方法中呼叫它是完全可以的。如果它阻塞了相當長的時間,例如超過 50 毫秒,那么從異步方法中呼叫它將違反微軟關于異步方法應如何表現的指南:
基于TAP的異步方法可以在回傳結果任務之前同步進行少量的作業,例如驗證引數和啟動異步操作。同步作業應保持在最低限度,以便異步方法能夠快速回傳。那么,如果ValidateEvent方法阻塞,而你又無能為力,你該怎么辦?AFAIK 你處于一個灰色地帶,所有的選擇都因為這樣或那樣的原因而不能令人滿意。
你可以讓它保持原樣,接受該方法違反了 Microsoft 的指導方針,記錄這一行為,并讓呼叫者選擇將
AddAsync包裹在Task.Run中,如果這對他們有利的話。
你可以將
ValidateEvent包裹在Task.Run中,就像你在問題中做的那樣。這違反了(部分地)微軟的另一條準則。不要為同步方法提供異步包裝器。你可以將你的
AddAsync方法分成兩部分,即同步的ValidateAdd和異步的AddAsync,期望呼叫者在呼叫一個方法后呼叫另一個。如果你的
AddAsync方法是一個與應用程式無關的庫的一部分,我會說選擇方案1。這就是 Microsoft 在一些內置 API 上的做法。如果AddAsync方法是特定于應用程式的,并且該應用程式有一個GUI(WinForms、WPF等),那么就很有可能采用選項2。對于GUI應用程式來說,保持UI的回應性是最重要的,所以Task.Run應該被包含在某個地方,而把它放在AddAsync中似乎是一個方便的地方。選項3可能是這個特定案例中最沒有吸引力的選項,因為驗證和添加是緊密耦合的操作,但是對于其他場景來說,它可能是一個不錯的選擇。轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/318048.html
標籤:
上一篇:異步和等待-難以理解
