protected override async Task ExecuteAsync(CancellationToken token) { // Create a token that can be cancelled to stop all running tasks var tokenSource = CancellationTokenSource.CreateLinkedTokenSource(token); // Execute startup activities and upon success send a startup signal await SendStartedSignalAsync(tokenSource.Token).ConfigureAwait(false); // Start sending liveness signal periodically var signalParallelTask = SendAliveSignalAsync(TimeSpan.FromSeconds(_probeConfiguration.LivenessSignalIntervalSeconds), tokenSource.Token); // Paralllelly execute background worker's jobs var workerParallelTask = _serviceImplementation.ExecuteAsync(tokenSource.Token); // If liveness or worker job throws exception or runs to completion then cancel everything and exit the program. var continuationTask = await Task.WhenAny(signalParallelTask, workerParallelTask).ConfigureAwait(false); // Awaiting on task returned by Task.WhenAny() bubbles exceptions in inner tasks await continuationTask.ConfigureAwait(false); // If any one of then run to completion then cancel the other await continuationTask.ContinueWith(t => tokenSource.Cancel()).ConfigureAwait(false); // Although all tasks will finish by now, background service will not cause the host to terminate. // You will have to implement IApplicationLifetime for that which may not make sense if there are multiple IHostedService implemented. // But, since kubernetes liveness probes are enabled, absence of alive.signal file will cause service to reboot. }