別のアプリケーション「B」の 4 つのインスタンスを監視する C# コンソール プログラム「A」があります。
コンソール プログラムは、「B」のインスタンスごとに 1 つのスレッドを作成し、各スレッドは を使用して「B」を起動しProcess.Start()
ます。次に、スレッドは次を使用して3秒間待機しますProcess.WaitForExit(3000);
その後、アプリケーション「B」のインスタンスが動作しているかどうかを確認します。OKなら、また待ちます。それ以外の場合、機能しない場合、または終了した場合は、再起動します。ユーザーがコンソール プログラムを閉じると、すべてのアプリケーションが終了することが期待されます。
ただし、コンソールの閉じるボタンを使用してアプリケーション「A」を閉じると、すべてのスレッドで WaitForExit() が再開され、アプリケーション「B」が再起動されます。
WaitForExit()
監視対象アプリ「B」の障害による再開なのか、メインアプリ「A」の終了による再開なのかを検出したい。この場合、アプリケーション「B」は再起動されず、問題は解決されます。
私は次を使用して終了イベントをキャプチャしようとしました:
[DllImport("Kernel32")]
public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);
問題は、ハンドラ ルーチンが呼び出される前に WaitForExit() が再開されたことです。
詳しくは:
Main() メソッドはスレッドを起動します。
for(int i = 0; i < 4; i++)
{
Thread t = new Thread(() => MonitorizeApp(arguments));
t.IsBackground = true;
t.Start();
}
メインアプリが終了しないように、スレッドをバックグラウンドからフォアグラウンドに変更しようとしましたが、結果は同じです。
各スレッドは、2 番目のアプリケーションの 1 つのインスタンスを起動して監視します。
MonitorizeApp(string arguments)
{
LaunchProcess(arguments);
while(!_closing)
{
appProcess.WaitForExit(3000);
if (!_closing)
{
if ((appProcess != null) && (!appProcess.HasExited))
DoSomeMonitoring();
else
{
Console.WriteLine("WARNING: The application finished");
Thread.Sleep(500);
if (!_closing)
{
Console.WriteLine("Re-launch");
LaunchProcess(arguments);
inicial = true;
}
}
}
}
Console.WriteLine("\nClosing...\n");
if(appProcess != null)
{
if(!appProcess.HasExited)
appProcess.Kill();
appProcess.Dispose();
}
}
_closing は、コンソールが閉じられたときにメイン スレッドから設定される変数です。SetConsoleCtrlHandler を使用してこれを行いました。
[DllImport("Kernel32")]
public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);
public delegate bool HandlerRoutine(CtrlTypes CtrlType);
private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
{
MonitoredApp.closing = true;
Thread.Sleep(1000);
closing = true;
Environment.Exit(-1);
return true;
}