Consider a service which needs to do different kinds of work simultaneously, e.g. process messages from a message queue or queues and post some changing info to some database once per a period of time.
I am used to create these 'workers' this way:
public void Start()
{
_queueProcessingTask = Task.Run(async () => await ProcessMessages(_cts.Token), _cts.Token);
_dataPostingTask = Task.Run(async () => await PostToDatabase(_cts.Token), _cts.Token);
}
So, we have a class, that keeps track of the two tasks and has a means of cancelling them. ProcessMessages
and PostToDatabase
are just private async Task-returning methods, containing infinite loops with some logic.
We capture a thread pool thread to run our method on, and the thread is going to be returned to the pool, when it reaches the first await
inside the logic. After this, thread pool threads will be running continuations throughout the logic.
There is also one way of starting these workers:
public void Start()
{
_queueProcessingTask = ProcessMessages(_cts.Token);
_dataPostingTask = PostToDatabase(_cts.Token);
}
private async Task ProcesMessages(CancellationToken token)
{
await Task.Yield();
// here goes our endless while loop with logic...
}
private async Task PostToDatabase(CancellationToken token)
{
await Task.Yield();
// here goes our endless while loop with logic...
}
In this example we don't call Task.Run
, we just call the methods, synchronously wait to get the awaitable out of the Task.Yield() and are given control back immediately. Then, a thread pool thread will be captured to run the continuations in our method logic like in the first case.
Both examples work identically concerning the observable behavior.
My questions are:
- Is there some overhead of capturing a separate thread using Task.Run, as opposed to doing a bare call of a method with Task.Yield inside?
- Are my assumptions about the scenarios in both cases correct? Is there anything I should think of additionally?
- What is the best way to have such workers in your service, and are there any general guidelines for this?