ChatGPT解决这个技术问题 Extra ChatGPT

如何正确退出 C# 应用程序?

我有一个用 C# 发布的应用程序。每当我通过单击红色退出按钮关闭主表单时,表单会关闭,但不会关闭整个应用程序。我在尝试关闭计算机时发现了这一点,随后被许多带有我添加的 MessageBox 警报的子窗口轰炸。

我试过 Application.Exit 但它仍然调用所有子窗口和警报。我也不知道如何使用 Environment.Exit 以及将哪个整数放入其中。

此外,每当我的表单调用 FormClosedFormClosing 事件时,我都会使用 this.Hide() 函数关闭应用程序;这会影响我的应用程序的行为吗?

不要处理 FormClosed 或 FormClosing
所以你说你只是隐藏表格而不是关闭它们?这可能是应用程序没有终止的原因,它仍然有打开(隐藏)的表单。
那么我应该将所有this.Hide()替换为this.Close()吗?
您不需要 Hide() 或 Close()。
发布有关关闭操作和事件的代码。

C
Community

来自 MSDN:

Application.Exit

通知所有消息泵它们必须终止,然后在处理完消息后关闭所有应用程序窗口。如果您已调用 Application.Run(WinForms 应用程序),这是要使用的代码,此方法会停止所有线程上所有正在运行的消息循环并关闭应用程序的所有窗口。

Environment.Exit

终止此进程并为底层操作系统提供指定的退出代码。这是您使用控制台应用程序时要调用的代码。

这篇文章 Application.Exit vs. Environment.Exit 指出了一个很好的提示:

您可以通过检查 System.Windows.Forms.Application.MessageLoop 属性来确定是否已调用 System.Windows.Forms.Application.Run。如果为真,则 Run 已被调用,您可以假设 WinForms 应用程序正在执行,如下所示。

if (System.Windows.Forms.Application.MessageLoop) 
{
    // WinForms app
    System.Windows.Forms.Application.Exit();
}
else
{
    // Console app
    System.Environment.Exit(1);
}

参考:Why would Application.Exit fail to work?


这对我来说真的很有用,因为我有一个 WinForms 应用程序,它有一个参数,所以它可以静默运行,因此不显示表单。当表单被隐藏时,Application.Exit() 无法退出应用程序,但 Environment.Exit(1) 就像一个魅力。
该问题未提及因错误而退出,因此退出代码应为零:Environment.Exit(0) 任何非零值都是特定于应用程序的错误代码,脚本可以使用它来采取适当的操作。 (这是新代码和 WinForms 应用程序,因此在这种情况下不太重要,但对于任何编写命令行工具的人来说都很好。)
Environment.Exit 也可用于表单应用程序。
如果我错了,请纠正我,但我认为之后的 return 声明会大大改进这种方法。据我了解,代码将在 Application.Exit() 之后继续执行,直到 return 语句。
@Bighted19 真的吗?你能详细说明一下这个机制吗?
S
Scott Chamberlain

我知道这不是您遇到的问题,但是可能发生这种情况的另一个原因是您在应用程序中打开了一个非后台线程。

using System;
using System.Threading;
using System.Windows.Forms;

namespace Sandbox_Form
{
    static class Program
    {
        private static Thread thread;

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            thread = new Thread(BusyWorkThread);
            thread.IsBackground = false;
            thread.Start();

            Application.Run(new Form());

        }

        public static void BusyWorkThread()
        {
            while (true)
            {
                Thread.Sleep(1000);
            }
        }
    }
}

IsBackgroundfalse 时,它将保持程序打开直到线程完成,如果您将 IsBackground 设置为 true,线程将不会保持程序打开。 BackgroundWokerThreadPoolTask 之类的东西都在内部使用 IsBackground 设置为 true 的线程。


S
Servy

顺便一提。每当我的表单调用 formclose 或表单关闭事件时,我都会使用 this.Hide() 函数关闭应用程序。这会影响我的应用程序现在的行为吗?

简而言之,是的。当主窗体(通过 Main 方法中的 Application.Run 启动的窗体)关闭(未隐藏)时,整个应用程序将结束。

如果您的整个应用程序在主窗体关闭时始终完全终止,那么您应该删除该窗体关闭处理程序。通过不取消该事件并在用户关闭它时让它们关闭,您将获得所需的行为。至于所有其他表单,如果您不打算再次显示相同的表单实例,您只需让它们关闭,而不是阻止关闭并隐藏它们。如果您再次显示它们,那么隐藏它们可能没问题。

如果您希望能够让用户为您的主表单单击“x”,但让另一个表单保持打开状态并且实际上成为“新”主表单,那么它会有点复杂。在这种情况下,您只需要隐藏您的主窗体而不是关闭它,但是您需要添加某种机制,当您确实希望您的应用程序结束时,它实际上会关闭主窗体。如果这是您所处的情况,那么您需要在问题中添加更多详细信息,描述哪些类型的应用程序应该和不应该实际结束程序。


A
Anton Tsches

在这种情况下,退出应用程序的最正确方法是覆盖 App.xaml.cs 中的 onExit() 方法:

protected override void OnExit(ExitEventArgs e) {
    base.OnExit(e); 
}

这允许您在退出事件发生时执行代码,但实际上不会导致退出事件发生。