Sharing Data Between BackgroundServices

Download full source code.

Background services are very useful when you want something to run quietly in the background while the rest of your application gets on with whatever it is doing.

Occasionally you might have more than one background service, and just sometimes you might want to share data between these two services.

In this example, there are two BackgroundService classes, Worker1 and Worker2, and they both loop forever with a delay at the end of each loop.

I use two ways of sharing info between the classes -

  1. A shared class that is passed to both by dependency injection.
  2. A static variable in Worker1 that can be accessed by Worker2.

Worker1 does two things - it increments a counter shared by dependency injection with Worker2, and updates a static variable with the current time. Then it sleeps for 200ms.

Worker2 does two things - it prints out the value of the shared counter, and prints out the value of the static variable from Worker1. Then it sleeps for 1000ms.

These two approaches are pretty simple once they are in place, I’m sure there are people who won’t like one or the other approach, and probably some who won’t like both approaches. But they will work for some scenarios, so give them a go.

The code is fairly simple.

Here is Worker1, not rocket science there -

 1namespace WorkerWithTwoServices;
 2
 3public class Worker1(SharedData sharedData) : BackgroundService
 4{
 5    public static TimeOnly SharedTime {get; private set;}
 6
 7    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
 8    {
 9        while (!stoppingToken.IsCancellationRequested)
10        {
11            Console.WriteLine($"Worker1 setting counter to {++sharedData.Counter}");
12            SharedTime = TimeOnly.FromDateTime(DateTime.Now);
13            await Task.Delay(200, stoppingToken);
14        }
15    }
16}

Worker2 is just as simple -

 1namespace WorkerWithTwoServices;
 2
 3public class Worker2(SharedData sharedData) : BackgroundService
 4{
 5    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
 6    {
 7        while (!stoppingToken.IsCancellationRequested)
 8        {
 9            Console.WriteLine($"\tWorker2 counter value is {sharedData.Counter}");
10            Console.WriteLine($"\tWorker2 Shared DateTime is {Worker1.SharedTime.ToLongTimeString()}");
11            await Task.Delay(1000, stoppingToken);
12        }
13    }
14}

There is SharedData class -

public class SharedData
{
    public int Counter { get; set; }
}

And the Program.cs file that adds the SharedData and Workers to the service collection.

using WorkerWithTwoServices;

var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddSingleton<SharedData>();
builder.Services.AddHostedService<Worker1>();
builder.Services.AddHostedService<Worker2>();

var host = builder.Build();
host.Run();

When I run it I get this output -

Worker1 setting counter to 1
        Worker2 counter value is 1
        Worker2 Shared DateTime is 8:12:58 PM
Worker1 setting counter to 2
Worker1 setting counter to 3
Worker1 setting counter to 4
Worker1 setting counter to 5
        Worker2 counter value is 5
        Worker2 Shared DateTime is 8:12:59 PM
Worker1 setting counter to 6
Worker1 setting counter to 7
Worker1 setting counter to 8
Worker1 setting counter to 9
Worker1 setting counter to 10
        Worker2 counter value is 10
        Worker2 Shared DateTime is 8:13:00 PM
Worker1 setting counter to 11
Worker1 setting counter to 12
Worker1 setting counter to 13
Worker1 setting counter to 14
Worker1 setting counter to 15
        Worker2 counter value is 15
        Worker2 Shared DateTime is 8:13:01 PM

That’s it, easy to share data between services.

Download full source code.

comments powered by Disqus

Related