Twe*_*nty 6 c# multithreading asp.net-core-3.0
因此,在ASP.Net Core的MSDN 中,它向您展示了如何使用托管服务创建后台任务。甚至还有一个特定的段落解释了如何创建后台队列。
现在我的问题是,该ExecuteAsync方法是否已经在自己的线程中运行,还是需要先调用Task.Run?
Will a BackgroundService always run in a new Thread?不。
BackgroundService没有指定任何有关线程的内容。它唯一要求的是返回 a 的重载Task,只要服务启动,该重载就保持活动状态。如果需要,您甚至可以返回已完成的任务。
如果你检查源代码,你会发现根本没有假设:
protected abstract Task ExecuteAsync(CancellationToken stoppingToken);
public virtual Task StartAsync(CancellationToken cancellationToken)
{
_executingTask = ExecuteAsync(_stoppingCts.Token);
if (_executingTask.IsCompleted)
{
return _executingTask;
}
return Task.CompletedTask;
}
Run Code Online (Sandbox Code Playgroud)
服务方法的线程行为取决于实现者,即您。如果ExecuteAsync在让步之前阻塞,则整个服务都会阻塞。如果该方法永远不会产生,则对其自身的调用StartAsync将被阻塞并导致整个应用程序出现问题。
如果ExecuteAsync在第一个服务之前做了一些昂贵的事情await,那么其他服务的启动也会被延迟。
这意味着Task.Run如果服务在第一次屈服之前需要执行任何昂贵的操作(即第一次调用await.
该
ExecuteAsync方法会在自己的线程中运行吗
假设ExecuteAsync是一个async方法 ( public async Task ExecuteAsync)
Tl;Dr 这取决于
async意味着该线程可以await编辑。await会停顿主线程当前的执行,直到结果返回async。这会将当前线程释放回线程池以供重新使用。然后,当async返回时,一个新线程(可能取决于您实际如何调用它)被从线程池中拉出以继续执行。这称为上下文切换。
如果这个方法不是真正的,async那么什么也不会发生,它会像不是一个async方法一样运行。
如果此方法显式创建Task(using Task.Run) 那么async线程将创建awaitthis Task。因此,任务使用一个新线程,该async方法将释放它的线程,并在任务返回时获取一个新线程。但这并不是零和,因为上下文切换的成本很高。这就是为什么您应该只使用async IO 密集型方法,因为在 CPU 密集型进程中通常会降低效率而不是提高效率。
我建议您阅读Stephen Cleary 关于该主题的优秀博客