-1

I have a .NET Core console application that I am running as a Windows Service in .NET Core 2.1. I will end up having multiple BackgroundService worker classes that will end up doing web calls. Some of these web calls rely on Authentication tokens that are fetch from their own AuthTokenWorker BackgroundService. I plan on saving those tokens within one worker class and sharing the value with the other worker classes.

How do I do that? Can I use .ConfigureAppConfiguration and use an in-memory collection? If I update a token in that configuration from one Worker, will the others using the same configuration through DI receive the updated value? Is doing that method thread safe?

In the past, I used a generic static Configuration class with a ConcurrentDictionary and just saved/fetched values from different classes, but I am new to .NET Core and want to know the appropriate way to achieve this.

eg.

Program.cs

static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureServices((hostBuilderContext, serviceCollection) =>
        {
            serviceCollection.AddHttpClient<SClient>();
            serviceCollection.AddHttpClient<DClient>();
            serviceCollection.AddHostedService<SWorker>();
            serviceCollection.AddHostedService<DWorker>();
        }).UseWindowsService();

}

SWorker.cs

I want to use the public property within DWorker.cs

public SClient(ILogger<STSTokenClient> logger, HttpClient client)
{
    _logger = logger;
    _client = client;
}

public SToken Token { get; internal set;}

Since I need an object to reference the property, can I inject it through the Constructor?

DWorker.cs

public DWorker(ILogger<DWorker> logger, SWorker sWorker,
    DClient dClient)
{
    _logger = logger;
    _sWorker = sWorker;
    _dClient = dClient;
}


protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    ...
    var token = await _dClient.FetchTokenAsync(_sWorker.Token);
}
Jimenemex
  • 3,104
  • 3
  • 24
  • 56
  • Wouldn't be enough to have a shared memory between these Background services? Like a Redis memory storage where you could store and retrieve in memory data. – Bruno Jul 19 '20 at 13:59
  • @Bruno I'm looking for something that can be shared between these background services that's already provided by .NET. – Jimenemex Jul 20 '20 at 00:31
  • then you should consider interprocess communication, as explained in here: https://stackoverflow.com/questions/528652/what-is-the-simplest-method-of-inter-process-communication-between-2-c-sharp-pro But I personally would create a webapi and use it as a "layer" of communication would be the simplest way to achieve what you want. – Bruno Jul 20 '20 at 07:10

1 Answers1

1

I plan on saving those tokens within one worker class and sharing the value with the other worker classes.

Mutating configuration might work, but that's an odd way to approach this problem. The more natural approach would be to use something like IMemoryCache with well-known keys.

Note that the GetOrCreate and GetOrCreateAsync extension methods for IMemoryCache are not atomic. If you want an async-compatible "refresh this token, but if it's already being refreshed then share that refresh request" kind of operation, then you'll need to build that yourself. If you need that, I have an AsyncCache that can help.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • This sounds like it'll solve my issue, what's your `AsyncCache` details? – Jimenemex Jul 23 '20 at 05:31
  • [My `AsyncCache` is in a Gist](https://gist.github.com/StephenCleary/39a2cd0aa3c705a984a4dbbea8275fe9). It's not fully tested and may be incomplet and inkorrect. – Stephen Cleary Jul 23 '20 at 11:36