[英]Async/await with/without awaiting (fire and forget)
我有以下代碼:
static async Task Callee()
{
await Task.Delay(1000);
}
static async Task Caller()
{
Callee(); // #1 fire and forget
await Callee(); // #2 >1s
Task.Run(() => Callee()); // #3 fire and forget
await Task.Run(() => Callee()); // #4 >1s
Task.Run(async () => await Callee()); // #5 fire and forget
await Task.Run(async () => await Callee()); // #6 >1s
}
static void Main(string[] args)
{
var stopWatch = new Stopwatch();
stopWatch.Start();
Caller().Wait();
stopWatch.Stop();
Console.WriteLine($"Elapsed: {stopWatch.ElapsedMilliseconds}");
Console.ReadKey();
}
#1 以最簡單的方式觸發和遺忘。 #2 只是等待。 有趣的東西從#3 開始。 調用背后的深層邏輯是什么?
我知道在 ASP.NET 中使用 fire'n'forget 警告,如這里所指出的。 我問這個,因為我們正在將我們的應用程序移動到服務結構,在那里我們不再可以使用HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => await LongMethodAsync());
建議是簡單地用Task.Run
替換它。
我看到Task.Run
運行一個新線程,那么 #3 和 #5 之間有什么區別?
我問這個,因為我們正在將我們的應用程序移動到服務結構,在那里我們不再可以使用 HostingEnvironment.QueueBackgroundWorkItem(asyncCancellationToken => await LongMethodAsync()); 建議是簡單地用 Task.Run 替換它。
這是個糟糕的建議。 您應該使用一個單獨的后台進程,通過隊列與您的 Web 前端分開。
調用背后的深層邏輯是什么?
“26.《Fire and Forget》很好,只要你永遠不會真正忘記。” 馬克西姆 26 。
如果您執行任何類型的火災並忘記場景,您將面臨吞咽異常的巨大風險。 吞下任何異常——尤其是致命的——是異常處理的致命罪過。 你最終得到的只是內存中的一個程序,它會產生更難以理解和可重現的異常。 所以永遠不要開始。 這是有關該材料的兩篇不錯的文章:
http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx http://www.codeproject.com/Articles/9538/Exception-Handling-Best-Practices-in -網
Full on Threads 能夠吞下異常是出了名的。 事實上,你必須努力不吞下它們,然后在它們完成后檢查它們是否有。 您應該至少有一些后續任務來記錄(和可能的暴露)異常。 否則你真的會后悔那個“火了就忘”。
希望有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.