0

I have .NET Core console application containing two independent tasks that should be running in parallel for the entire life-time of the application. I was thinking to use BackgroundService:

class BackgroundTaskOne : BackgroundService
{
    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                // do long running task for the entire life-time of application
                while(true)
                {
                    // do work one
                }
            }
            catch (Exception e)
            {
                // log
            }
        }

        return Task.CompletedTask;
    }
}

class BackgroundTaskTwo : BackgroundService
{
    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                // do long running task for the entire life-time of application
                while(true)
                {
                    // do work two
                }
            }
            catch (Exception e)
            {
                // log
            }
        }

        return Task.CompletedTask;
    }
}

And register them like this:

services.AddHostedService<BackgroundTaskOne>();
services.AddHostedService<BackgroundTaskTwo>();

But these are going to run in order. So I have two questions:

  1. Is there a way to make these two run in parallel?
  2. Are there any other alternatives to run two long-running background processes in .NET Core in parallel?
2
  • Have you look at MSDN's Task-based asynchronous programming? Lots of good ideas in there. You can create Tasks, you can create whole Threads... Commented Apr 21, 2020 at 19:20
  • add await Task.Yield() as the first call in the ExecuteAsync method Commented Nov 7, 2024 at 10:46

2 Answers 2

1

The docs of BackgroundService.ExecuteAsync say

The implementation should return a task that represents the lifetime of the long running operation(s) being performed.

Your implementation returns a completed task when the whole work is done. In fact you implemented it to run sync and not async and that is the reason for not running parallel.

Here is a sample implementation with some fake async work:

class BackgroundTaskOne : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                // do work one
                await Task.Delay( 100 );
            }
            catch (Exception e)
            {
                // log
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Ah I see. Actually the work I am performing in the try block is the actual long-running task that needs to be running for the entire lifetime of the application (just updated the question), so awaing that wouldn't help. I want to fire and forget these two tasks.
It does not matter how long the task is running, you have to have a real task and not a sync operation and returning a completed task at the end
1

As documentation says: https://github.com/dotnet/AspNetCore.Docs/blob/master/aspnetcore/fundamentals/host/hosted-services.md

No further services are started until ExecuteAsync becomes asynchronous, such as by calling await.

As long as you do not have async clause mentioned at the ExecuteAsync method above, I suspect your method is synchronous at whole. This is why two services are called sequentially, not in parallel. Give them a break, introduce good amount of awaitable code.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.