So in the MSDN for ASP.Net Core it shows you how to create Background Tasks with hosted services. There is even a specific paragraph which explains how you can create a Background Queue.
Now my question is, will the ExecuteAsync
method run in its own thread already, or do I need to call Task.Run
first?
Will a BackgroundService always run in a new Thread?
No.
BackgroundService
doesn't specify anything about threading. The only thing it asks is for an overload that returns a Task
, that remains active as long as the service is up. You can even return a completed task if you want.
If you check the source code you'll see that there's no assumption at all :
protected abstract Task ExecuteAsync(CancellationToken stoppingToken);
public virtual Task StartAsync(CancellationToken cancellationToken)
{
_executingTask = ExecuteAsync(_stoppingCts.Token);
if (_executingTask.IsCompleted)
{
return _executingTask;
}
return Task.CompletedTask;
}
The threading behavior of the service method is up to the implementor, ie you. If ExecuteAsync
blocks before yielding, the entire service blocks. If the method never yields, the call to StartAsync
itself will block and cause problems for the entire application.
If ExecuteAsync
does something expensive before the first await
, starting other services will be delayed as well.
This means that you may need to use Task.Run
if the service needs to do anything expensive before yielding for the first time, ie the first call to await
.
will the
ExecuteAsync
method run in its own thread
Presuming ExecuteAsync
is an async
method (public async Task ExecuteAsync
)
Tl;Dr it depdends
async
means that this thread can be await
ed. await
will park the current execution of the main thread until the result of the async
returns. This will release the current thread back into the thread pool for re-use. Then when the async
returns a new thread (maybe depending on how you actually call this) is pulled out of the thread pool to continue execution. This is called context switching.
If this method is not truly async
then nothing really happens, it run as if it's not an async
method.
If this method explicitly creates a Task
(using Task.Run
) then the async
thread will await
this Task
. So the Task uses a new thread and the async
method will release it's thread and get a new one when the Task returns. This isn't a zero sum though as the context switching is expensive. This is why you should only async
IO bound methods as you typically loose efficiency not gain in CPU bound processes.
I'd suggest you read Stephen Cleary's excellent blogs on the subject
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With