/// <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);
                    }
        }
Ejemplo n.º 2
0
        /// <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));
 }