To make it simple,
Let say I have a gRPC service:
At Startup.cs
, I added the dependencies the services needed.
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
// Add dependencies
services.AddSingleton<IDoSomething1, DoSomething1>();
services.AddSingleton<IDoSomething2, DoSomething2>();
services.AddSingleton<IDoSomething3, DoSomething3>();
...
}
It is working fine. But now, I want to do have some jobs running at the background (like querying a DB/another service for some updates).
Hence, I do something like below (using Timer + BackgroundWorker) at Program.cs
.
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
...
// Use the Startup class as shown above, so that I can using the dependencies added
webBuilder.UseStartup<Startup>();
}
public static void Main(string[] args)
{
// CreateHostBuilder -> Startup -> Dependencies added
using (var app = CreateHostBuilder(args).Build())
{
app.Start();
// Use Timer + BackgroundWorker here
BackgroundWorker backgroundWorker = new();
backgroundWorker.DoWork += BackgroundWorker_DoWork;
System.Timers.Timer timer = new();
timer.Interval = 2000;
timer.Enabled = true;
timer.Elapsed += (object sender, System.Timers.ElapsedEventArgs args) => backgroundWorker.RunWorkerAsync(app.Services);
app.WaitForShutdown();
}
}
private static void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
IServiceProvider sp = (IServiceProvider)e.Argument;
// Need to call GetRequiredService explicitly instead of automatically done by automatic constructor dependency injection
IDoSomething1 doSomething1 = sp.GetRequiredService<IDoSomething1>();
IDoSomething2 doSomething2 = sp.GetRequiredService<IDoSomething2>();
IDoSomething3 doSomething3 = sp.GetRequiredService<IDoSomething3>();
...
}
Although the code above should work, it does not seems elegant to me, because it needs to call GetRequiredService explicitly instead of automatically done by automatic constructor dependency injection like the gRPC service class.
Is any better way to do so? I mean something like app.AddBackgroundJob(...)
?
Check out BackgroundService class and especially Timed background tasks example which might be what are you looking for. Once your logic is implemented in such class it is plugged into ASP.NET via:
services.AddHostedService<TimedHostedService>();