C# Application.Exit()首先执行哪个操作
当我在MSDN上阅读Application.Exit()的文档时,它说: 通知所有消息泵它们必须终止,然后在处理消息后关闭所有应用程序窗口 据我所知,为了通知所有消息泵终止,此方法最终将向应用程序消息队列发布WM_QUIT消息。发布消息后,该方法将关闭每个窗口(通过MSDN)。问题出现在这里,当此方法尝试关闭每个窗口时,WM_QUIT消息本不应被处理,但MSDN表示“在处理完消息后,它关闭所有窗口”C# Application.Exit()首先执行哪个操作,c#,.net,winforms,C#,.net,Winforms,当我在MSDN上阅读Application.Exit()的文档时,它说: 通知所有消息泵它们必须终止,然后在处理消息后关闭所有应用程序窗口 据我所知,为了通知所有消息泵终止,此方法最终将向应用程序消息队列发布WM_QUIT消息。发布消息后,该方法将关闭每个窗口(通过MSDN)。问题出现在这里,当此方法尝试关闭每个窗口时,WM_QUIT消息本不应被处理,但MSDN表示“在处理完消息后,它关闭所有窗口” 文件似乎与我的推断相矛盾。这里有什么问题,非常感谢您的帮助。有趣的问题;使用,让我们看看Appl
文件似乎与我的推断相矛盾。这里有什么问题,非常感谢您的帮助。有趣的问题;使用,让我们看看
Application.Exit()
的作用:
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[DllImport("QCall", CharSet = CharSet.Unicode)]
internal static extern void _Exit(int exitCode);
我们看到,关键的方法是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();
}
PostQuit()是发送WM_QUIT
消息的工具。因此,我们也应该考虑何时使用代码>应用程序。THealEnguly.Debug“/CODE”被调用,并且它似乎总是在窗体关闭之后,尽管我很高兴在那里被纠正。
因此,订单似乎关闭了所有表单,然后发送WM_退出消息。我认为你是对的,文档中的事件顺序可能是错误的
这也证实了我们经常看到的另一个副作用;当应用程序关闭但后台仍有线程运行时,exe仍将位于正在运行的应用程序列表中。表单已经关闭,但仍然有那个流氓线程在嗡嗡地运行,阻止Exit()完成
如前所述:
线程可以是背景线程,也可以是前景线程。
背景线程与前景线程相同,只是
后台线程不阻止进程终止。一劳永逸
属于进程的前台线程已终止,公共
语言运行库结束该过程。任何剩余的后台线程
已停止且未完成
(来自)
我还想知道Environment.Exit
的作用是什么:
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[DllImport("QCall", CharSet = CharSet.Unicode)]
internal static extern void _Exit(int exitCode);
它有效地调用操作系统来终止进程;这将终止所有窗口,几乎没有任何优雅;例如,OnFormClosing可能永远不会被触发。作为这种大规模终止的一部分,它还将[我不太愿意使用尝试,因为我从未见过它失败]杀死任何线程,包括消息循环运行的“主”线程 为什么你认为WM_QUIT消息不会被处理?一个更好的问题是,“由于这个操作顺序的考虑,你有什么问题?”问题中没有一个问号…@IcyBrk你真的应该把你的答案作为评论发布,但别担心,我在下面的帖子中添加了一个关于ExitThreadCore
的片段。您的“rogue线程”使进程保持打开状态的原因是,它不是在后台运行的,而是一个前台线程。在所有前台线程终止之前,进程无法终止。这就是为什么你应该将你的“背景”线程IsBackground
属性设置为true
@Tergiver谢谢你的澄清,非常感谢。谢谢dash,你澄清了事实,谢谢你的详细挖掘,我仍然有疑问,你能告诉我ExitThreadCore()的确切功能吗,我尝试使用Reflector阅读源代码,但不是很成功。