/で実行されているDOTNET COREアプリケーションをgracefullyシャットダウンする方法はありますか?[〜#〜] docker [〜#〜]?はいの場合、どのイベントを聞く必要がありますか?
キャンセルリクエストがあれば、キャンセルトークンを現在のメソッドに渡し、それらが機能している間はシャットダウンを延期したいだけです。
一般的な情報ではなく、ドットネットコアに関連するサンプルコード、参照リンクなどを探しています
[〜#〜] update [〜#〜]この質問は docker containerはConsole.ReadLine( ).netコアコンソールアプリケーションで すぐに終了する問題がないため。 Windows.SystemsEvents.SessionEnding のようなイベントを利用する必要があり、_
Console.CancelKeyPress
_に依存したり、WebHostBuilder()
を実装したりすることは適切ではありません。
.NET Core 2.0では、AppDomain.CurrentDomain.ProcessExit
イベントを使用できます。これはLinuxのDockerで正常に機能します。 AssemblyLoadContext.Default.Unloading
は、.NET Core2.0より前でもおそらく同様に機能します。
System.Consoleには、CancelKeyPressというイベントがあります。これは、sigintイベントがdotnetに渡されたときに発生すると思います。
System.Console.CancelKeyPress += (s,e) => { /* do something here */};
2.0.0-preview2-006497を使用していくつかのテストを行い、AssemblyLoadContext.Default.UnloadingDockerがSIGTERM/SIGINTをコンテナに送信すると発生します。
サンプルコードは次のようになります。
System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += ctx =>
{
// code here...
};
詳細については、この問題も参照してください: https://github.com/aspnet/Hosting/issues/87
コンテナがLinuxで実行されている場合は、Loader.AssemblyLoadContext.Default.Unloading
SIGTERMシグナルをトラップできるため機能しますが、Windowsにはこれに相当するメカニズムがありません( dotnet issue )。これは、元々 Gist からSetConsoleCtrlHandler
を使用して、Windowsでシャットダウン通知を処理するための回答です。
namespace Routeguide
{
using System;
using System.Threading;
...
class Program
{
[DllImport("Kernel32")]
internal static extern bool SetConsoleCtrlHandler(HandlerRoutine handler, bool Add);
internal delegate bool HandlerRoutine(CtrlTypes ctrlType);
internal enum CtrlTypes
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT,
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
}
static void Main(string[] args)
{
// do the server starting code
Start();
....
var shutdown = new ManualResetEvent(false);
var complete = new ManualResetEventSlim();
var hr = new HandlerRoutine(type =>
{
Log.Logger.Information($"ConsoleCtrlHandler got signal: {type}");
shutdown.Set();
complete.Wait();
return false;
});
SetConsoleCtrlHandler(hr, true);
Console.WriteLine("Waiting on handler to trigger...");
shutdown.WaitOne();
Console.WriteLine("Stopping server...");
// do the server stopping code
Stop();
complete.Set();
GC.KeepAlive(hr);
}
}
}