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 -
- A shared class that is passed to both by dependency injection.
- A static variable in
Worker1
that can be accessed byWorker2
.
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.