興味深い質問; ILSpyを使用して、何をするかを見てみましょうApplication.Exit()
。
重要な方法はExitInternal
private static bool ExitInternal()
{
bool flag = false;
lock (Application.internalSyncObject)
{
if (Application.exiting)
{
return false;
}
Application.exiting = true;
try
{
if (Application.forms != null)
{
foreach (Form form in Application.OpenFormsInternal)
{
if (form.RaiseFormClosingOnAppExit())
{
flag = true;
break;
}
}
}
if (!flag)
{
if (Application.forms != null)
{
while (Application.OpenFormsInternal.Count > 0)
{
Application.OpenFormsInternal[0].RaiseFormClosedOnAppExit();
}
}
Application.ThreadContext.ExitApplication();
}
}
finally
{
Application.exiting = false;
}
}
return flag;
}
すべてがうまくいけば、アプリケーションは最初にすべてのフォームを閉じ、次に見逃したフォームをすべて閉じ、最後に呼び出しますApplication.ThreadContext.ExitApplication();
ExitApplicationの一部として、クリーンアップが表示されます。
private static void ExitCommon(bool disposing)
{
lock (Application.ThreadContext.tcInternalSyncObject)
{
if (Application.ThreadContext.contextHash != null)
{
Application.ThreadContext[] array = new Application.ThreadContext[Application.ThreadContext.contextHash.Values.Count];
Application.ThreadContext.contextHash.Values.CopyTo(array, 0);
for (int i = 0; i < array.Length; i++)
{
if (array[i].ApplicationContext != null)
{
array[i].ApplicationContext.ExitThread();
}
else
{
array[i].Dispose(disposing);
}
}
}
}
}
// System.Windows.Forms.ApplicationContext
/// <summary>Terminates the message loop of the thread.</summary>
/// <filterpriority>1</filterpriority>
public void ExitThread()
{
this.ExitThreadCore();
}
ExitThreadCoreは何をしますか?
まあ、それはスレッドを直接殺しませんが、それはプロセスを開始します:
ExitThreadとExitThreadCoreは、実際にはスレッドを終了させません。これらのメソッドは、ApplicationオブジェクトがリッスンするThreadExitイベントを発生させます。次に、Applicationオブジェクトはスレッドを終了します。
しかし、本当に興味深いビットはで起こるようですarray[i].Dispose(disposing)
この方法の一部として、次のようになります。
if (this.messageLoopCount > 0 && postQuit)
{
this.PostQuit();
}
PostQuit()はWM_QUIT
メッセージを送信するものです。そのため、いつ呼び出されるかについても考慮する必要Application.ThreadContext.Dispose
があります。フォームが閉じられた後のようですが、そこで修正されてうれしいです。
したがって、注文はすべてのフォームを閉じているように見えます。次に、WM_QUITメッセージを送信します。私はあなたが正しいと思います、ドキュメントは実際に間違った順序でイベントを持っているかもしれません...
また、私たちがよく目にする別の副作用も確認しています。アプリケーションが閉じられていても、バックグラウンドで実行されているスレッドがまだある場合、exeは実行中のアプリケーションのリストに残ります。フォームは閉じられましたが、Exit()が完了しないようにハミングしながら、その不正なスレッドがまだあります。
Tergiverが言及しているように:
スレッドは、バックグラウンドスレッドまたはフォアグラウンドスレッドのいずれかです。バックグラウンドスレッドは、バックグラウンドスレッドがプロセスの終了を妨げないことを除いて、フォアグラウンドスレッドと同じです。プロセスに属するすべてのフォアグラウンドスレッドが終了すると、共通言語ランタイムはプロセスを終了します。残りのバックグラウンドスレッドはすべて停止され、完了しません。
(Thread.IsBackgroundThreadから)
私はまた何をするのか疑問に思いましたEnvironment.Exit
:
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[DllImport("QCall", CharSet = CharSet.Unicode)]
internal static extern void _Exit(int exitCode);
プロセスを強制終了するためにOSを効果的に呼び出します。これにより、すべてのウィンドウがほとんど猶予なしで終了します。たとえば、OnFormClosingが起動することはおそらくないでしょう。この大規模な終了の一環として、メッセージループが実行されている「メイン」スレッドを含むすべてのスレッドを強制終了します[失敗するのを見たことがないので、試行を使用することを躊躇します]。