using Microsoft.Extensions.Hosting; using System; using System.Threading; using System.Threading.Tasks; namespace Ordering.BackgroundTasks.Tasks.Base { // Copyright(c) .NET Foundation.All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. /// /// Base class for implementing a long running . /// IMPORTANT: This base class is implemented in .NET Core 2.1 - Since this microservice is still in .NET Core 2.0, we're using the class within the project /// When .NET Core 2.1 is released, this class should be removed and you should use the use implemented by the framework /// https://github.com/aspnet/Hosting/blob/712c992ca827576c05923e6a134ca0bec87af4df/src/Microsoft.Extensions.Hosting.Abstractions/BackgroundService.cs /// /// public abstract class BackgroundService : IHostedService, IDisposable { private Task _executingTask; private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource(); /// /// This method is called when the starts. The implementation should return a task that represents /// the lifetime of the long running operation(s) being performed. /// /// Triggered when is called. /// A that represents the long running operations. protected abstract Task ExecuteAsync(CancellationToken stoppingToken); /// /// Triggered when the application host is ready to start the service. /// /// Indicates that the start process has been aborted. public virtual Task StartAsync(CancellationToken cancellationToken) { // Store the task we're executing _executingTask = ExecuteAsync(_stoppingCts.Token); // If the task is completed then return it, this will bubble cancellation and failure to the caller if (_executingTask.IsCompleted) { return _executingTask; } // Otherwise it's running return Task.CompletedTask; } /// /// Triggered when the application host is performing a graceful shutdown. /// /// Indicates that the shutdown process should no longer be graceful. public virtual async Task StopAsync(CancellationToken cancellationToken) { // Stop called without start if (_executingTask == null) { return; } try { // Signal cancellation to the executing method _stoppingCts.Cancel(); } finally { // Wait until the task completes or the stop token triggers await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite, cancellationToken)); } } public virtual void Dispose() { _stoppingCts.Cancel(); } } }