加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – Application.Exit()哪个操作是第一个

发布时间:2020-12-15 07:49:25 所属栏目:百科 来源:网络整理
导读:当我在MSDN上阅读Application.Exit()文档时,它说: 通知所有消息泵,它们必须终止,然后在消息处理完成后关闭所有应用程序窗口. 在我的理解中,要通知所有消息泵终止,该方法将最终向应用消息队列发送WM_QUIT消息.在发布消息之后,该方法将关闭每个窗口(通过MSDN)
当我在MSDN上阅读Application.Exit()文档时,它说:

通知所有消息泵,它们必须终止,然后在消息处理完成后关闭所有应用程序窗口.

在我的理解中,要通知所有消息泵终止,该方法将最终向应用消息队列发送WM_QUIT消息.在发布消息之后,该方法将关闭每个窗口(通过MSDN).问题出现在这里,当这种方法尝试关闭每个窗口时,WM_QUIT消息应该没有被处理,但是MSDN表示“它在消息被处理之后关闭所有的窗口”.

文件似乎与我的推论是矛盾的.这里有什么问题,任何帮助都非常感激.

解决方法

有趣的问题使用 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 and ExitThreadCore do not actually cause the thread to
terminate. These methods raise the ThreadExit event to which the
Application object listens. The Application object then terminates the
thread.

然而,真正有趣的一点似乎是发生在数组[i] .Dispose(处置)

作为这种方法的一部分,我们看到:

if (this.messageLoopCount > 0 && postQuit)
{
    this.PostQuit();
}

PostQuit()是什么发送WM_QUIT消息.所以我们也应该考虑Application.ThreadContext.Dispose是什么时候调用的,并且它总是似乎在表单关闭后,虽然我很高兴在那里被纠正.

所以命令似乎是关闭所有窗体,然后发送WM_QUIT消息.我认为你是对的,这些文件实际上可能会导致错误的事件发生.

这也证实了我们经常看到的另一个副作用当应用程序关闭但仍然有一个线程在后台运行时,exe仍将在运行的应用程序的列表中.表格已经关闭,但仍然有流氓线索,哼唱着阻止Exit()完成.

正如Tergiver所提到的:

A thread is either a background thread or a foreground thread.
Background threads are identical to foreground threads,except that
background threads do not prevent a process from terminating. Once all
foreground threads belonging to a process have terminated,the common
language runtime ends the process. Any remaining background threads
are stopped and do not complete.

(Thread.IsBackgroundThread)

我也想知道Environment.Exit的作用:

[SecurityCritical,SuppressUnmanagedCodeSecurity]
[DllImport("QCall",CharSet = CharSet.Unicode)]
internal static extern void _Exit(int exitCode);

它有效地呼吁操作系统杀死进程;这将终止所有的窗户,一点恩典; OnFormClosing可能永远不会被触发.作为这个批发终止的一部分,它也将[我犹豫使用尝试,因为我从来没有看到它失败)杀死任何线程,包括消息循环正在运行的“主”线程.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读