为什么 Application.Exit 无法正常工作?

29

我有一个应用程序,在取消对话框时出现了奇怪的错误。如果取消了该对话框,应用程序无法继续执行,因此退出,但由于某种原因它没有正常工作,并因此保持运行状态并崩溃。

我已调试此问题,但不知何故,应用程序在Application.Exit调用之后仍然继续运行。我正在调试模式下运行,这很重要,因为少量代码依赖于定义RELEASE变量。以下是我的应用程序退出代码。我已跟踪代码并进入了ExitApp方法,但它仍继续执行并返回控制权给调用者,最终导致崩溃。

这是一个通过远程桌面连接提供报告的应用程序,所以退出代码有点奇怪。它试图在RELEASE模式下终止远程会话,但只有当测试运行时我才想要关闭开发机器。

    private void ExitApp()
    {
        HardTerminalExit();
        Application.Exit();
    }

    // When in Debug mode running on a development computer, this will not run to avoid shutting down the dev computer
    // When in release mode the Remote Connection or other computer this is run on will be shut down.
    [Conditional("RELEASE")]
    private void HardTerminalExit()
    {
        WTSLogoffSession(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, false);
    }

我已经在Application.Exit代码行下方运行了调试器,但什么也没有发生,当我跨过那行代码时控制权返回给调用者。

发生了什么?这是一个Windows Forms应用程序。


对我来说,我曾经执行了一个不同的形式.Show()调用 - 关闭了那个窗口,但application.exit()失败了,我将其更改为form.ShowDialog()调用,一切都变得更好了。 - Michael Shelnutt
10个回答

48

这是一篇扩展了你正在思考的相同思路的文章:http://www.dev102.com/2008/06/24/how-do-you-exit-your-net-application/

基本上:

  • Environment.Exit - 来自MSDN:终止此进程并将指定的退出代码传递给底层操作系统。在使用控制台应用程序时调用此代码。

  • Application.Exit - 来自MSDN:通知所有消息泵必须终止,然后在处理完消息后关闭所有应用程序窗口。如果您已调用Application.Run(WinForms应用程序),则使用此方法停止所有运行的消息循环和关闭应用程序的所有窗口。关于此方法还有一些问题,请阅读MSDN页面中的相关信息。

这是另一个讨论:链接

这篇文章提出了一个好建议:

您可以通过检查System.Windows.Forms.Application.MessageLoop属性来确定是否已调用System.Windows.Forms.Application.Run。 如果返回true,则已经调用Run并且可以认为WinForms应用程序正在执行如下操作。

if (System.Windows.Forms.Application.MessageLoop)
{
  // Use this since we are a WinForms app
  System.Windows.Forms.Application.Exit();
}
else
{
  // Use this since we are a console app
  System.Environment.Exit(1);
}

4
我在调用 exit 方法后添加了额外的返回操作。这解决了该问题。 - Tony Peterson
1
@TonyPeterson 这个要求的原因是 Exit 调用会在队列上放置一个 Exit 消息,但会继续执行直到应用程序处理退出请求,因此你需要返回以结束执行。哇,刚意识到这有多久了,抱歉。 - Basic
1
嗨@TonyPeterson,请问你能把你添加的“additional return”的代码发一下吗?非常感谢!提前谢谢! - user900202
我将我的代码从仅显示一个表单更改为通过Application.Run使用它。ReportDisplay rd = new ReportDisplay(u, cd.reports, u.root,emails); Application.Run(rd); - Tony Peterson
控制台或使用Application.Run()启动的“无窗体”消息循环怎么样?即使使用自己的ApplicationContext和方法() => ThreadExit(),我也无法杀死这个野兽... - Sebastian Xawery Wiśniowiecki

7

最近我遇到了这个问题(即Application.Exit无法正确终止使用Application.Run(new Form())的win-forms中的消息泵),我发现如果在构造函数中生成新线程或启动后台工作者,这将阻止Application.Exit运行。

将所有的“RunWorkerAsync”调用从构造函数移动到窗体加载方法中:

public Form()
{
  this.Worker.RunWorkerAsync();
}

转移到:

public void Form_Load(object sender, EventArgs e)
{
  this.Worker.RunWorkerAsync();
}

6
尝试使用 Environment.Exit(exitCode)

3

我在许多情况下都遇到过这种情况,我使用Thread.CurrentThread.Abort()来关闭进程。似乎Application.Exit没有正确地与当前线程连接起来。


2

请确保您的应用程序中没有Console.ReadLine();,这样Environment.Exit(1);将起作用并关闭您的应用程序。


2

同时确保应用程序中运行的任何线程都将IsBackground属性设置为true。非后台线程容易阻止应用程序退出。


1

我创建了以下代码,可以在任何地方退出应用程序。您不必担心表单是否正在运行,测试会确定并调用适当的退出方法。

    public void exit(int exitCode)
    {
        if (System.Windows.Forms.Application.MessageLoop)
        {
            // Use this since we are a WinForms app
            System.Windows.Forms.Application.Exit()
        }
        else
        {
            // Use this since we are a console app
            System.Environment.Exit(exitCode);
        }
    } //* end exit()

0
    private void frmLogin_FormClosing(object sender, FormClosingEventArgs e)
    {

        if (e.CloseReason == CloseReason.UserClosing)
        {
            DialogResult result = MessageBox.Show("Do you really want to exit?", "Dialog Title", MessageBoxButtons.YesNo);
            if (result == DialogResult.Yes)
            {
                Environment.Exit(0);
            }
            else
            {
                e.Cancel = true;
            }
        }
        else
        {
            e.Cancel = true;
        }


    }

1
欢迎,Jordan。你能否为我们补充一下代码是如何帮助回答问题的呢? - Lockszmith
虽然这段代码可能回答了问题,但提供有关它如何以及/或为什么解决问题的附加上下文将改善答案的长期价值。您可以在帮助中心找到有关编写良好答案的更多信息:https://stackoverflow.com/help/how-to-answer。祝你好运! - nima

0
尝试这个:
在 Program.cs 文件中:
Application.Run(new form()); 之后添加 Application.Exit();

0

这个应用程序是否在Main方法中使用Application.Run()运行?否则,Application.Exit()将无法工作。

如果您编写了自己的Main方法并且想要停止应用程序,则只能通过从Main方法返回(或终止进程)来停止。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接