【发布时间】:2021-10-19 20:47:42
【问题描述】:
我在 Asp.Net Core Web API 中实现了一个 Microsoft.Extensions.Hosting.BackgroundService,它在 ExecuteAsync 内部有一个阻塞调用,但令人惊讶的是(对我来说)它实际上并没有阻塞我的应用程序,我想知道原因.
根据我能找到的BackgroundService源代码的不同版本,Task ExecuteAsync方法在StartAync内部被火速调用了。来源如下。
public virtual Task StartAsync(CancellationToken cancellationToken)
{
// Store the task we're executing
_executingTask = ExecuteAsync(_stoppingCts.Token);
// If the task is completed then return it, this will bubble cancellation and failure to the caller
if (_executingTask.IsCompleted)
{
return _executingTask;
}
// Otherwise it's running
return Task.CompletedTask;
}
据我了解,await 调用的延续(即它下面的任何内容)将在任务返回后调用此异步方法的同一 SynchronizationContext 中执行。如果这是真的,那么为什么这个延续代码(具有阻塞调用)不会阻塞我的应用程序?
举例说明:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await Task.Yield();
Foo(); // Foo blocks its executing thread until an I/O operation completes.
}
由于永远不会等待 ExecutedAsync,因此该方法的继续(即 Foo 调用)将在最初触发 ExecuteAsync 任务的同一同步上下文中执行(它将在主如果我理解正确,请线程)。
我怀疑 Asp.Net 运行时必须有自己的SynchronizationContext,它实际上在不同的线程中执行异步延续或类似的东西。
任何人都可以在这里解释一下吗?
【问题讨论】:
标签: c# asp.net-core async-await