I have added a Timer
to Startup
class of an ASP.Net Core
application. It fires on some time period and do operations like logging a sample text. I need it to be able to do database driven operations like adding a record to a table. So I try to get AppDbContext
from DI but it is always null. Please see the code:
public class Scheduler
{
static Timer _timer;
static bool _isStarted;
static ILogger<Scheduler> _logger;
const int dueTimeMin = 1;
const int periodMin = 1;
public static void Start(IServiceProvider serviceProvider)
{
if (_isStarted)
throw new Exception("Currently is started");
_logger = (ILogger<Scheduler>)serviceProvider.GetService(typeof(ILogger<Scheduler>));
var autoEvent = new AutoResetEvent(false);
var operationClass = new OperationClass(serviceProvider);
_timer = new Timer(operationClass.DoOperation, autoEvent, dueTimeMin * 60 * 1000, periodMin * 60 * 1000);
_isStarted = true;
_logger.LogInformation("Scheduler started");
}
}
public class OperationClass
{
IServiceProvider _serviceProvider;
ILogger<OperationClass> _logger;
AppDbContext _appDbContext;
public OperationClass(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
_logger = (ILogger<OperationClass>)serviceProvider.GetService(typeof(ILogger<OperationClass>));
_appDbContext = (AppDbContext)_serviceProvider.GetService(typeof(AppDbContext));
}
public void DoOperation(Object stateInfo)
{
try
{
_logger.LogInformation("Timer elapsed.");
if (_appDbContext == null)
throw new Exception("appDbContext is null");
_appDbContext.PlayNows.Add(new PlayNow
{
DateTime = DateTime.Now
});
_appDbContext.SaveChanges();
}
catch (Exception exception)
{
_logger.LogError($"Error in DoOperation: {exception.Message}");
}
}
}
And here it is the code from Startup
:
public Startup(IHostingEnvironment env, IServiceProvider serviceProvider)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
AppHelper.InitializeMapper();
Scheduler.Start(serviceProvider);
}
I guess I am calling Scheduler.Start
in a wrong place. Seems that AppDbContext
is not ready yet.
What is the correct place to call Scheduler.Start
?