![](/img/trans.png)
[英]How to use async/await in scenario with multiple tasks with each task requiring a new async/await
[英]how to use async and await so that it will create a different task or each request
我是asp.net核心和異步編程的新手。 下面是我的代碼
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var work = await TaskQueue.DequeueAsync(stoppingToken);
while (!stoppingToken.IsCancellationRequested)
{
redirect(work);
}
}
public async Task redirect(Func<CancellationToken, Task> work)
{
await work();
}
所以在這里,當我運行程序並調試它時,光標首先進入ExecuteAsync方法,而從while循環進入重定向方法。 重定向方法仍然是異步的,它將等待工作方法。 所以我認為它不是異步運行的。
我希望當光標進入工作方法時,它將啟動一個新任務(線程)。
當我運行程序並對其進行調試時
您正在觀察的行為是Visual Studio 試圖提供幫助。 它具有處理異步方法的特殊代碼,因此,當您說“進入下一行”時,它不會突然轉移到某些完全不相關的方法。 它將轉到該方法的下一行。
我希望當光標進入工作方法時,它將啟動一個新任務(線程)。
任務不是線程。 特別是, async
方法創建的任務不會在線程上運行; 它們只是狀態對象,可以在async
方法完成時通知其他代碼。
我建議閱讀我的async
介紹 ,並通過async
最佳實踐進行跟進。
您嘗試使用Async-Await
的方式存在一些誤解,網絡上有足夠的內容,以下是詳細信息:
所以在這里,當我運行程序並調試它時,光標首先進入ExecuteAsync方法,而從while循環進入重定向方法。 重定向方法仍然是異步的,它將等待工作方法。 所以我認為它不是異步運行的
await
所做的是釋放調用上下文,而處理在后台進行,這有助於系統保持響應狀態,因此系統具有可伸縮性/線程池來滿足進一步的請求,因此, await
唯一不做的事情就是阻塞調用線程/上下文中,在代碼中看到的調試器中,它將等待完成。
現在,什么類型的處理
work
是IO還是Compute
如果是IO
,那就是真正在服務器上使用異步處理的地方,因為線程池線程已釋放,並且如果與ConfigureAwait(false)
一起使用,則不需要重新輸入相同的上下文來處理響應,這是庫期望的。 如果是計算的,那么它就可以像WPF這樣的UI很好地工作,因為Ui線程保持了響應能力,但是處理仍然從當前池中奪走了線程,並且可用性有限/稀缺。
關於你的代碼
redirect(work)
,而后者又確實await work
,它釋放了調用者,但等待它完成才能執行下一個Async操作 List<Task>
類的集合中,並在等待Task.WhenAll
時將所有聚合的任務放在一起,而當您異步等待單個代表性Task
使其完成時,仍然可以不是像當前代碼中那樣大膽地調用,而是阻止完整的聚合列表,它由@TheGeneral在注釋中指定,因此有助於更好地處理,因為所有任務都一起執行 await work()
不正確,編譯錯誤,這需要一個取消令牌作為I / p參數 redirect(work)
,異步等待應貫穿整個調用鏈 您的代碼的修改版本
假設您需要Task.WhenAll
並且您正在執行基於IO的異步操作,則以下代碼應為:
protected override async Task ExecuteAsync(CancellationToken stoppingQueueToken,CancellationToken stopWorkToken)
{
var work = await TaskQueue.DequeueAsync(stoppingQueueToken);
List<Task> taskList = new List<Task>();
while (!stoppingQueueToken.IsCancellationRequested)
{
taskList.Add(redirect(work, stopWorkToken));
}
await Task.WhenAll(taskList);
}
public async Task redirect(Func<CancellationToken, Task> work, CancellationToken stopWorkToken)
{
await work(stopWorkToken);
}
我已經自由地介紹了用於工作取消的Extra Cancellation Token,因為工作處理僅在退出循環時才開始一次,在此之前它僅聚合任務,然后將它們一起在后台進行處理,並假定IO獲得最大利益。 在這里,調試器也會阻塞,但是對於所有任務,只需一次調用
如果您堅持使用當前代碼,則只需進行以下更改:
protected override async Task ExecuteAsync(CancellationToken stoppingQueueToken)
{
var work = await TaskQueue.DequeueAsync(stoppingQueueToken);
List<Task> taskList = new List<Task>();
while (!stoppingQueueToken.IsCancellationRequested)
{
await redirect(work, stoppingQueueToken);
}
}
public async Task redirect(Func<CancellationToken, Task> work, CancellationToken stoppingQueueToken)
{
await work(stoppingQueueToken);
}
更多細節
Task
和Thread
不相同且可以互換,多個任務可以在同一線程上執行 ThrowIfCancellationRequested
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.