C# 中关闭当前线程的四种方式

.net强制退出主窗口的方法——Application.Exit()方法和Environment.Exit(0)方法

.net类库已经帮助我们实现了窗口的关闭,如果此窗口是系统的主窗口,关闭此窗口即应该退出了整个应用程序。
但事实上有时候并不是这样的,关闭窗口,只是停止了当前窗口的消息循环。
系统主窗口,实质上是Main函数中开始消息循环的窗口,这个消息循环结束后,Main函数就基本上完成了历史使命,整个应用程序自然就结束了。
Application.Exit()方法是终止所有线程上的消息循环,一般情况下,无论在什么地方调用此方法,程序就能退出。
但是如果你在程序中加入了某些耗时甚至是死循环的线程,那么即使是消息循环终止,程序也依然不会结束。
比较温和比较合适的做法是结束消息循环之前,终止所有自己新建的线程。
有时候我们连自己也搞不清楚到底是那些顽固的线程在执行,就需要用点暴力的手段了。.net为我们提供了Environment.Exit(0)方法,调用此方法,应用程序即强制退出。

当你打开一个子窗体,进行某项操作时,如果字窗体中有循环操作时。如果运行中我关闭子窗体,发现窗体虽然关闭了,但子窗体中的循环程序却没有退出,一直在 执行,并占用着系统资源,直到循环结束,才真正的释放资源。尽管你在字窗体的Closed事件中写了如下代码:
      
       private void frmFileDisposal_Closed(object sender, System.EventArgs e)
      {
          this.Dispose();
          this.Close();
      }
从查MSDN和从网上查资料可以知道,Dispose()方法,虽然能释放当前窗体的资源,却不能强制结束循环,
   要想强制突出当前程序要用:System.Environment.Exit(int exitcode)方法;该方法:终止当前进程并为基础操作系统提供指定的退出代码。

如下则问题解决:
    private void frmFileDisposal_Closed(object sender, System.EventArgs e)
      {         
          System.Environment.Exit(System.Environment.ExitCode);   
          this.Dispose();
          this.Close();
      }

或者把它放到事件里:
    while (MessageBox.Show("退出当前窗体?", "", MessageBoxButtons.YesNo) ==   DialogResult.No)
     {
       for(int j=1; j<=i; j++)
       {
          listBox1.Items.Add(j);
       }       
    }
   System.Environment.Exit(System.Environment.ExitCode);   

还有一种方法: System.Threading.Thread.CurrentThread.Abort();
                           或者           Process.GetCurrentProcess().Kill()
                            或者        Application.ExitThread();
                            或者        Application.ExitThread()


不过以上方法,都是强制直接退出了整个程序,不只是关闭子窗体。可能还会引发某些问题,
我感觉最好方法的就是,在子窗体的Closing事件中,写循环退出条件,这样就可以避免某些未知的错误,而且可以只关闭子窗体,并释放子窗体占用的资源


Application.Exit(); 方法停止在所有线程上运行的所有消息循环,并关闭应用程序的所有窗口

Application.Exit 是一种强行退出方式,就像 Win32 的 PostQuitMessage()。它意味着放弃所有消息泵,展开调用堆栈,并将执行返回给系统。

在 Windows(Win32 或 .NET)中关闭应用程序的正确方式是关闭它的主应用程序窗口(例如 Form.Close)。主消息泵结束后依然存在的任何窗口都需要手动关闭。在应用程序退出之前通过调用 Form.Close 或 Form.Dispose 来关闭窗口是清除窗口的良好做法,但这需要您有意识地去做。我们需要记住,.NET Framework 的 OnClosing() 是 Win32 的托管版本的 WM_CLOSE,而非 WM_DESTROY。

另外,如果您使用 form.Close(),通过处理 OnClosing 或 OnClosed 事件,就可以让您的应用程序清理内容、关闭文件等。如果您通过 Application.Exit 强行退出应用程序,就无法调用这些事件。

Application.Exit(); 方法停止在所有线程上运行的所有消息循环,并关闭应用程序的所有窗口
Application.Exit 是一种强行退出方式,就像 Win32 的 PostQuitMessage()。它意味着放弃所有消息泵,展开调用堆栈,并将执行返回给系统
Environment.Exit(0)方法,调用此方法,应用程序即强制退出

I have a windows form application. It is accessing a backend SQL server. The
data access are wrapped in modules. If the data access failed, I wanted to
display a popup error message and then exit the application. I tried to use
Application.Exit(), Application.ExitThread, and Environment.Exit(). They all
have kind weird problem.
1. Applicaiton.Exit() This method is called within an exception block, after
displaying a message box to the user. It seems it is not doing anything. The
rest of code will be executed in order like nothing happened.

2. Application.ExitThread() The same as Application.Exit()

3. Thread.CurrentThread.Abort() This method will cause ThreadAbort
Exception, so I have to handle this exception from layer to layer.

4. Environment.Exit() In exception catch block, I display the message box,
and then call this method. This caused the application to exit, but the
message box just flashed and disappeared

### 安全终止或关闭 C# 线程的最佳实践 在 C#/.NET 中,安全地终止线程是一个重要的主题。以下是关于如何正确关闭线程的一些最佳实践以及注意事项。 #### 使用 `CancellationToken` 来实现线程的安全取消 .NET 提供了 `CancellationToken` 机制来帮助开发者优雅地停止线程执行。通过传递一个 `CancellationToken` 到任务中,可以在需要的时候请求取消该任务的运行[^1]。这种方式不仅提高了代码的可维护性和安全性,还减少了死锁和资源泄漏的风险。 ```csharp using System; using System.Threading; class Program { static void Main() { CancellationTokenSource cts = new CancellationTokenSource(); CancellationToken token = cts.Token; Thread workerThread = new Thread(() => { while (true) { if (token.IsCancellationRequested) { Console.WriteLine("线程正在被请求取消..."); break; // 响应取消信号并退出循环 } Console.WriteLine("线程正在工作..."); Thread.Sleep(500); } }); workerThread.Start(); // 模拟等待一段时间后发送取消命令 Thread.Sleep(2000); cts.Cancel(); // 请求取消线程的工作 workerThread.Join(); // 主线程等待子线程完成后再继续 Console.WriteLine("主线程结束"); } } ``` #### 处理未捕获异常以防止应用崩溃 如果在线程中发生了未处理的异常,默认情况下会引发整个应用程序的终止行为[^2]。因此,在设计多线程程序时,应该始终考虑对潜在的错误进行适当的捕捉和记录。 ```csharp try { SomeDangerousOperation(); } catch (Exception ex) { LogError(ex); // 将错误写入日志文件或其他持久化存储位置 throw; // 如果必要的话重新抛出以便进一步分析或者通知上层调用者 } finally { CleanupResources(); // 清理任何已分配但不再使用的资源 } ``` #### 后台线程的行为特点 当创建一个新的线程实例时,可以通过设置其 `IsBackground` 属性决定它是否作为前台还是后台线程运行。对于后者来说,一旦所有的前台线程都已经结束了它们的生命期,则无论这些背景进程当前状态为何种情况都会随之一起销毁[^3]。 ```csharp var backgroundThread = new Thread(new ParameterizedThreadStart(ThreadJob)); backgroundThread.IsBackground = true; // 设置为后台线程 backgroundThread.Start(someParameter); // 当最后一个非后台线程结束后, 所有的后台线程都将自动终结. ``` #### 推荐使用 Task 并发模型代替传统 Thread 类型 尽管可以直接利用低级别的 `System.Threading.Thread` 对象来进行并发控制,但是推荐尽可能采用更高级别的抽象——即基于 `Task Parallel Library (TPL)` 的解决方案[^4]。这是因为 TPL 不仅简化了许多复杂的同步逻辑而且还内置了很多实用的功能比如进度报告、超时支持等等。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值