/// <inheritdoc /> public async Task <TResult> RunAsync <TResult>(IDeadManSwitchWorker <TResult> worker, DeadManSwitchOptions options, CancellationToken cancellationToken) { if (worker == null) { throw new ArgumentNullException(nameof(worker)); } using (var deadManSwitchSession = _deadManSwitchSessionFactory.Create(options)) using (var watcherCTS = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) using (var workerCTS = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, deadManSwitchSession.DeadManSwitchContext.CancellationTokenSource.Token)) { _logger.Trace("Running worker {WorkerName} using a dead man's switch", worker.Name); var deadManSwitch = deadManSwitchSession.DeadManSwitch; var deadManSwitchWatcher = deadManSwitchSession.DeadManSwitchWatcher; var workerTask = Task.Run(async() => await worker.WorkAsync(deadManSwitch, workerCTS.Token).ConfigureAwait(false), CancellationToken.None); var watcherTask = Task.Run(async() => await deadManSwitchWatcher.WatchAsync(watcherCTS.Token).ConfigureAwait(false), CancellationToken.None); var task = await Task.WhenAny(workerTask, watcherTask).ConfigureAwait(false); if (task == workerTask) { watcherCTS.Cancel(); return(await workerTask.ConfigureAwait(false)); } workerCTS.Cancel(); throw new OperationCanceledException(workerCTS.Token); } }
/// <inheritdoc /> public async Task RunAsync(IInfiniteDeadManSwitchWorker worker, DeadManSwitchOptions options, CancellationToken cancellationToken) { if (worker == null) { throw new ArgumentNullException(nameof(worker)); } _logger.Trace("Starting infinite worker loop for {WorkerName} using a dead man's switch", worker.Name); using (var deadManSwitchSession = _deadManSwitchSessionFactory.Create(options)) using (var watcherCTS = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) { var deadManSwitch = deadManSwitchSession.DeadManSwitch; var deadManSwitchWatcher = deadManSwitchSession.DeadManSwitchWatcher; var deadManSwitchContext = deadManSwitchSession.DeadManSwitchContext; var watcherTask = Task.Factory.StartNew(() => deadManSwitchWatcher.WatchAsync(watcherCTS.Token), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); var iteration = 1; while (!cancellationToken.IsCancellationRequested) { using (var workerCTS = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, deadManSwitchContext.CancellationToken)) { _logger.Trace("Beginning work iteration {Iteration} of infinite worker {WorkerName} using a dead man's switch", iteration, worker.Name); var workerTask = Task.Run(() => worker.WorkAsync(deadManSwitch, workerCTS.Token), CancellationToken.None); try { await workerTask.ConfigureAwait(false); _logger.Debug("Worker {WorkerName} completed gracefully", worker.Name); deadManSwitch.Notify("Worker task completed gracefully"); } catch (OperationCanceledException) { _logger.Warning("Worker {WorkerName} was canceled", worker.Name); // Restart watcher await watcherTask.ConfigureAwait(false); deadManSwitch.Notify("Worker task was canceled"); watcherTask = Task.Factory.StartNew(() => deadManSwitchWatcher.WatchAsync(watcherCTS.Token), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); } } iteration++; } _logger.Information("Cancellation requested, cleaning up infinite worker loop for {WorkerName}", worker.Name); watcherCTS.Cancel(); await watcherTask.ConfigureAwait(false); } _logger.Trace("Infinite worker loop for {WorkerName} has stopped", worker.Name); }
public IDeadManSwitchSession Create(DeadManSwitchOptions deadManSwitchOptions) { return(Session = _inner.Create(deadManSwitchOptions)); }