private void ConsumeJobs(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { var job = jobQueue.Take(); while (true) { var retryPeriodInMilliseconds = 5000; try { dispatcher.Dispatch(BackgroundJobActions.MarkAsProcessing(job.Id)); // Check if the job is now obsolete (because a newer version of the project device exists) var jobProjectDeviceVersion = dispatcher.Dispatch(ProjectDeviceActions.GetProjectDeviceVersion(job.ProjectDeviceVersionId)); var projectDeviceVersions = dispatcher.Dispatch(ProjectDeviceActions.GetProjectDeviceVersionsForProjectDevice(jobProjectDeviceVersion.ProjectDeviceId)); if (projectDeviceVersions.Select(pdv => pdv.Version).Max() > jobProjectDeviceVersion.Version) { dispatcher.Dispatch(BackgroundJobActions.MarkAsCancelled(job.Id, "A newer version of the project device now exists")); break; } piSyncService.ProcessProjectDeviceVersion(job); dispatcher.Dispatch(BackgroundJobActions.MarkAsComplete(job.Id)); break; } catch (Exception ex) { dispatcher.Dispatch(BackgroundJobActions.MarkAsErrored(job.Id, ex.Message, ex.StackTrace)); if (cancellationToken.IsCancellationRequested) { break; } cancellationToken.WaitHandle.WaitOne(retryPeriodInMilliseconds); } } } }