using System;
using System.Threading;
using System.Threading.Tasks;
namespace CsvHelper.DocsGenerator
{
public static class ConsoleHost
{
///
/// Block the calling thread until shutdown is triggered via Ctrl+C or SIGTERM.
///
public static void WaitForShutdown()
{
WaitForShutdownAsync().GetAwaiter().GetResult();
}
///
/// Returns a Task that completes when shutdown is triggered via the given token, Ctrl+C or SIGTERM.
///
/// The token to trigger shutdown.
public static async Task WaitForShutdownAsync(CancellationToken token = default(CancellationToken))
{
var done = new ManualResetEventSlim(false);
using (var cts = CancellationTokenSource.CreateLinkedTokenSource(token))
{
AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: string.Empty);
await WaitForTokenShutdownAsync(cts.Token);
done.Set();
}
}
///
/// Runs an application and block the calling thread until host shutdown.
///
/// The to run.
public static void Wait()
{
WaitAsync().GetAwaiter().GetResult();
}
///
/// Runs an application and returns a Task that only completes when the token is triggered or shutdown is triggered.
///
/// The to run.
/// The token to trigger shutdown.
public static async Task WaitAsync(CancellationToken token = default(CancellationToken))
{
//Wait for the token shutdown if it can be cancelled
if (token.CanBeCanceled)
{
await WaitAsync(token, shutdownMessage: null);
return;
}
//If token cannot be cancelled, attach Ctrl+C and SIGTERN shutdown
var done = new ManualResetEventSlim(false);
using (var cts = new CancellationTokenSource())
{
AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: "Application is shutting down...");
await WaitAsync(cts.Token, "Application running. Press Ctrl+C to shut down.");
done.Set();
}
}
private static async Task WaitAsync(CancellationToken token, string shutdownMessage)
{
if (!string.IsNullOrEmpty(shutdownMessage))
{
Console.WriteLine(shutdownMessage);
}
await WaitForTokenShutdownAsync(token);
}
private static void AttachCtrlcSigtermShutdown(CancellationTokenSource cts, ManualResetEventSlim resetEvent, string shutdownMessage)
{
Action ShutDown = () =>
{
if (!cts.IsCancellationRequested)
{
if (!string.IsNullOrWhiteSpace(shutdownMessage))
{
Console.WriteLine(shutdownMessage);
}
try
{
cts.Cancel();
}
catch (ObjectDisposedException) { }
}
// Wait on the given reset event
resetEvent.Wait();
};
AppDomain.CurrentDomain.ProcessExit += delegate { ShutDown(); };
Console.CancelKeyPress += (sender, eventArgs) =>
{
ShutDown();
//Don't terminate the process immediately, wait for the Main thread to exit gracefully.
eventArgs.Cancel = true;
};
}
private static async Task WaitForTokenShutdownAsync(CancellationToken token)
{
var waitForStop = new TaskCompletionSource