[英]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.