個人的備忘録

調べたり思いついたりした事の置き場

Console.CancelKeyPressのバグ

.Net Frameworkのコンソールアプリケーションでは、Console.CancelKeyPressイベントにハンドラを登録することでCtrl+Cが押された時の動作をハンドルできる。
そのままプログラムを終了させたくない場合はConsoleCancelEventArgs.Canceltrueを設定する。

ConsoleCancelEventHandler handler = (s, e) =>
{
    Console.WriteLine("Cancelled!");
    e.Cancel = true;
};
Console.CancelKeyPress += handler;

特定の画面だけハンドルしたかったのでハンドラを削除すると、再登録した時に何故か反応しない。

ConsoleCancelEventHandler handler = (s, e) =>
{
    Console.WriteLine("Cancelled!");
    e.Cancel = true;
};
Console.CancelKeyPress += handler;  // OK
Console.CancelKeyPress -= handler; 
Console.CancelKeyPress += handler;  // NG

調べてみると、.Net Frameworkのバグのようだ。(4.5.2で確認)
CancelKeyPressから最後のハンドラが削除されるとWindowsに登録されたコールバックが削除されてしまうらしい。

最後のハンドラが削除されないようにダミーを登録しておくことで回避できる。

Console.CancelKeyPress += delegate { };
ConsoleCancelEventHandler handler = (s, e) =>
{
    Console.WriteLine("Cancelled!");
    e.Cancel = true;
};
Console.CancelKeyPress += handler;  // OK
Console.CancelKeyPress -= handler;
Console.CancelKeyPress += handler;  // OK