I have the following code:
public async Task ExecuteJobs(CancellationToken ct)
{
var newJobs = (await _jobRepository.GetAsync(ct, x => x.State == State.Created && x.RunDate <= DateTimeOffset.Now)).ToList();
foreach (var job in newJobs)
{
try
{
UpdateJobState(job, State.Scheduled);
switch (job.Type)
{
case JobType.AnnualReportConfiguration:
UpdateJobState(job, State.Running);
await _reportConfigurationDataService.GetAndSendData(ct);
break;
case JobType.Assets:
UpdateJobState(job, State.Running);
await _assetsDataService.GetAndSendData(ct);
break;
case JobType.BrfEconomy:
UpdateJobState(job, State.Running);
await _brfEconomyDataService.GetAndSendData(ct);
break;
case JobType.Customer:
UpdateJobState(job, State.Running);
await _customerDataService.GetAndSendData(ct);
break;
case JobType.ElectedRepresentative:
UpdateJobState(job, State.Running);
await _representativeDataService.GetAndSendData(ct);
break;
case JobType.Person:
UpdateJobState(job, State.Running);
await _personDataService.GetAndSendData(ct);
break;
case JobType.RealEstate:
UpdateJobState(job, State.Running);
await _realEstateDataService.GetAndSendData(ct);
break;
case JobType.TextTemplate:
UpdateJobState(job, State.Running);
await _textTemplateDataService.GetAndSendData(ct);
break;
}
UpdateJobState(job, State.Finished);
}
catch(Exception ex)
{
UpdateJobState(job, State.Error);
}
}
}
private void UpdateJobState(Job job, State jobState)
{
job.State = jobState;
_jobRepository.Update(job);
}
I wonder how I can run the jobs independently of each other, instead of waiting for each other? How can I do this in a good way, consider that entity framework is not thread-safe?
I have tried something like this:
case JobType.Assets:
UpdateJobState(job, State.Running);
var task = Task.Run(() => _assetsDataService.GetAndSendData(ct));
task.ContinueWith((task) =>
{
UpdateJob(job.Id, State.Finished, ct);
});
break;
private async Task UpdateJob(Guid id, State jobState, CancellationToken ct)
{
var job = (await _jobRepository.GetAsync(ct, x => x.Id == id)).FirstOrDefault();
job.State = jobState;
_jobRepository.Update(job);
}
But that don't work because I get an exception saying that the DbContext is used in another thread.
Can you guys give me some feedback of how I should do it?
EDIT:
I solved the entity framework issue by implementing a factory, and It worked.
However,
I get the following error when my Task is completed:
Cannot access a disposed object.\r\nObject name: 'IServiceProvider'.
This is when this code is executed:
estateTask.ContinueWith((estateTask) => UpdateJob(job.Id, State.Finished, ct));
private async Task UpdateJob(Guid Id, State jobState, CancellationToken ct)
{
try
{
var job = (await _jobRepository.Get(x => x.Id == Id, ct)).FirstOrDefault(); // error here
job.State = jobState;
_jobRepository.Update(job);
}
catch(Exception ex)
{
throw;
}
}
How can I solve this?