先给个结论:线程异常不捕获,程序直接崩——这可不是“没报错”,而是根本没机会处理。

c#如何处理线程异常_c#处理线程异常完整教程与实战案例

很多开发者在排查崩溃问题时,常常陷入一个误区:到处加 try-catch 就以为万事大吉。但对于C#的多线程场景,异常处理完全是另一套规则。哪一个线程、哪一类任务,都有自己专属的异常通道,漏掉一个环节,程序就等着崩给你看。

WinForms UI线程异常必须用 Application.ThreadException

按钮点击、Timer 的 Tick 事件、DataBinding 的更新操作——所有在 UI 线程上发生的同步异常,都不会被你写的 try-catch 捕获到,也不会触发全局的 AppDomain.UnhandledException。它们只认 Application.ThreadException 这一条路。为什么?因为 Windows 消息循环内部的异常处理机制,不允许外部拦截。

关键点在于:

后台线程(Thread/ThreadPool)异常只能靠 AppDomain.UnhandledException

显式创建的 new Thread 或者未 awaitTask.Run,一旦抛出未捕获的异常,就会触发 AppDomain.UnhandledException。但要注意,这个事件有一个“不可撤销”的特点:程序会在事件处理完以后立即终止,没有商量余地。

容易踩坑的地方:

async Task 方法里的异常必须 await 才能捕获

这可能是最容易忽略的地方。async Task 方法内部 throw 不会立刻导致程序崩溃,而是让返回的 Task 进入 Faulted 状态。如果你不 await,这个异常就“沉到底”了,后续完全无感知。

错误写法:DoWorkAsync(); —— 异常被吞掉,无声无息。

正确写法:await DoWorkAsync();,然后外层用 try-catch 才能捕获到。

如果实在需要 fire-and-forget 的场景(比如日志上报),至少要做到:加 .ConfigureAwait(false),并且确保 TaskWait() 或检查 task.Exception

还有一个绝对要避免的:async void(除了事件处理器的特殊情况)。async void 的异常会直奔 AppDomain.UnhandledException,连拦截的机会都没有。

自定义异常类漏掉构造函数会导致反序列化失败

跨 AppDomain、WCF、旧版 Remoting 这些场景下,异常对象需要被序列化传递。如果自定义异常只写了 public class MyException : Exception,运行时反序列化就会静默失败,或者直接抛 SerializationException

正确的做法:

说到底,异常处理不是“写个 catch 就完事”那么简单。UI 线程、后台线程、async 线程各自有独立的异常通道,漏掉任何一个环节,程序就在那里等着崩给你看。这才是真正的“硬功夫”。

本文转载于:https://www.php.cn/faq/2339476.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。