diff --git a/src/Microsoft.AspNetCore.Hosting/WebHostExtensions.cs b/src/Microsoft.AspNetCore.Hosting/WebHostExtensions.cs
index 3dcd322602..38807e11e3 100644
--- a/src/Microsoft.AspNetCore.Hosting/WebHostExtensions.cs
+++ b/src/Microsoft.AspNetCore.Hosting/WebHostExtensions.cs
@@ -23,6 +23,32 @@ namespace Microsoft.AspNetCore.Hosting
return host.StopAsync(new CancellationTokenSource(timeout).Token);
}
+ ///
+ /// Block the calling thread until shutdown is triggered via Ctrl+C or SIGTERM.
+ ///
+ /// The running .
+ public static void WaitForShutdown(this IWebHost host)
+ {
+ host.WaitForShutdownAsync().GetAwaiter().GetResult();
+ }
+
+ ///
+ /// Returns a Task that completes when shutdown is triggered via the given token, Ctrl+C or SIGTERM.
+ ///
+ /// The running .
+ /// The token to trigger shutdown.
+ public static async Task WaitForShutdownAsync(this IWebHost host, CancellationToken token = default(CancellationToken))
+ {
+ var done = new ManualResetEventSlim(false);
+ using (var cts = CancellationTokenSource.CreateLinkedTokenSource(token))
+ {
+ AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: string.Empty);
+
+ await host.WaitForTokenShutdownAsync(cts.Token);
+ done.Set();
+ }
+ }
+
///
/// Runs a web application and block the calling thread until host shutdown.
///
@@ -33,54 +59,30 @@ namespace Microsoft.AspNetCore.Hosting
}
///
- /// Runs a web application and returns a Task that only completes on host shutdown.
+ /// Runs a web application and returns a Task that only completes when the token is triggered or shutdown is triggered.
///
/// The to run.
- public static async Task RunAsync(this IWebHost host)
+ /// The token to trigger shutdown.
+ public static async Task RunAsync(this IWebHost host, CancellationToken token = default(CancellationToken))
{
+ // Wait for token shutdown if it can be canceled
+ if (token.CanBeCanceled)
+ {
+ await host.RunAsync(token, shutdownMessage: null);
+ return;
+ }
+
+ // If token cannot be canceled, attach Ctrl+C and SIGTERM shutdown
var done = new ManualResetEventSlim(false);
using (var cts = new CancellationTokenSource())
{
- Action shutdown = () =>
- {
- if (!cts.IsCancellationRequested)
- {
- Console.WriteLine("Application is shutting down...");
- try
- {
- cts.Cancel();
- }
- catch (ObjectDisposedException)
- {
- }
- }
-
- done.Wait();
- };
-
- AppDomain.CurrentDomain.ProcessExit += (sender, eventArgs) => shutdown();
- Console.CancelKeyPress += (sender, eventArgs) =>
- {
- shutdown();
- // Don't terminate the process immediately, wait for the Main thread to exit gracefully.
- eventArgs.Cancel = true;
- };
+ AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: "Application is shutting down...");
await host.RunAsync(cts.Token, "Application started. Press Ctrl+C to shut down.");
done.Set();
}
}
- ///
- /// Runs a web application and 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 Task RunAsync(this IWebHost host, CancellationToken token)
- {
- return host.RunAsync(token, shutdownMessage: null);
- }
-
private static async Task RunAsync(this IWebHost host, CancellationToken token, string shutdownMessage)
{
using (host)
@@ -107,24 +109,61 @@ namespace Microsoft.AspNetCore.Hosting
Console.WriteLine(shutdownMessage);
}
- token.Register(state =>
- {
- ((IApplicationLifetime)state).StopApplication();
- },
- applicationLifetime);
-
- var waitForStop = new TaskCompletionSource