C# 正在捕获线程中的系统异常
我知道捕捉System.Exception不是一个好的做法,除非是在应用程序的顶层。一根线怎么样?可以在线程的顶层捕获System.Exception吗 更新: 该线程是一个长时间运行的线程,只有在应用程序停止时才应该终止。因此,为了确保应用程序不会崩溃,我只需捕获System.Exception并记录错误。一切都被重新创造C# 正在捕获线程中的系统异常,c#,.net,exception,exception-handling,C#,.net,Exception,Exception Handling,我知道捕捉System.Exception不是一个好的做法,除非是在应用程序的顶层。一根线怎么样?可以在线程的顶层捕获System.Exception吗 更新: 该线程是一个长时间运行的线程,只有在应用程序停止时才应该终止。因此,为了确保应用程序不会崩溃,我只需捕获System.Exception并记录错误。一切都被重新创造 while (Terminate == false) { var discoveryClient = new Dis
while (Terminate == false)
{
var discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
try
{
var criteria = new FindCriteria(typeof(T));
criteria.Scopes.Add(new Uri(Scope));
var discovered = discoveryClient.Find(criteria);
discoveryClient.Close();
discoveryClient = null;
// do something with the endpoints
}
catch (OutOfMemoryException e)
{
m_Logger.LogException(e, "Exception when trying to discover clients (Contract: {0})", typeof(T).Name);
throw;
}
catch (Exception e)
{
m_Logger.LogException(e, "Exception when trying to discover clients (Contract: {0})", typeof(T).Name);
if (discoveryClient != null)
(discoveryClient as IDisposable).Dispose();
}
}
是的,这是个好主意:) 嗯,我不明白为什么人们认为捕捉顶级异常不是一个好主意。说真的,你抓不到他们
从实际的日常开发角度来看,如果您的后台线程有顶级异常,那么您希望了解它。你不希望应用程序崩溃,这是默认行为——令人惊讶的是,用户不喜欢这样。这是少数几个您肯定希望捕获异常并记录/恢复的地方之一。这取决于线程正在做什么以及应用程序中线程的上下文。一般来说,您应该遵循黄金经验法则:除非您知道如何处理异常,否则不要捕获异常。(我当然在简化,但这是经验法则) 因为我们讨论的是
System.Exception
,而不是某个子类,所以我假设您实际上不知道如何处理异常。记录错误并让应用程序终止(捕获无法处理的异常的唯一合法原因),而不从引发异常的线程中捕获异常,因此简短的回答是不,不确定
如果我没记错的话.NET1实际上捕获并吞并了在后台线程上引发的所有异常。这导致写得不好的程序出现了很多问题,微软改变了.NET 2中的行为,让异常导致应用程序崩溃——你可以想象,他们有很好的理由做出这样一个突破性的改变
关于后台工作人员的更新
:
请不要将BackgroundWorker
的使用模式误认为是“吞咽系统。异常情况
正常”。以下是文档的内容:
您的RunWorkerCompleted事件处理程序
应该经常检查
AsyncCompletedEventArgs.Error和
AsyncCompletedEventArgs。已取消
属性,然后再访问
RunWorkerCompletedEventArgs.Result
财产。如果引发了异常
或者如果手术被取消了,
访问
RunWorkerCompletedEventArgs.Result
属性引发异常
简单地说,选择忽略此建议或故意忽略返回值(否则仍将引发异常!)是一种糟糕的编程实践。我们通常不打算直接创建新线程。只有在少数情况下才是可以接受的。
因此,如果您确实使用new-Thread()
,尤其是在UI中,这将是不受欢迎的
我们鼓励使用BackgroundWorker
或Task
来封装线程异常处理,这样就不需要对catch
块进行异常处理
这4种情况是可以接受的,您需要自己的线程(来自): 我强烈建议您使用 要执行异步的线程池 无论何时计算绑定操作 可能的然而,有一些 你可能想要的场合 显式创建一个专用线程 执行某一特定任务 计算绑定操作。典型的 您可能希望创建一个专用的 线程,如果您要执行代码 这要求线程处于 不正常的特定状态 对于线程池线程。例如 我会创建一个专用线程,如果我 希望线程以特殊的速度运行 优先级(所有线程池线程都运行 以正常优先级,您不应该 改变线程池线程的 优先权)。我也会考虑 创建和使用我自己的线程,如果我 想让这条线成为前景 线程(所有线程池线程都是 背景线程),因此 防止应用程序死亡 直到我的线程完成其 任务我也会使用专用线程 如果计算绑定任务 极长的运行时间;这边,我 不会让线程池的 它试图弄明白的逻辑 是否创建一个附加的 线最后,我会使用专用的 线程如果我想开始一个线程 并可能通过 调用线程的中止方法 (在第21章“CLR托管”中讨论) 和AppDomains”)
从官方的角度来看,这不是一个好的做法,但有时是这样的 参数与在“主”线程上执行此操作的参数完全相同 一个主要的问题是,如果您接受了这样的错误,那么您的应用程序可能会非常不正确地运行—例如,它可能会覆盖重要的用户数据—而不是终止
如果您确实选择了这条路线,您可能需要小心从捕获中排除
ThreadAbortException
——如果有人中止工作线程(在您的应用程序中可能是这样,也可能不是这样),这是一个“预期的异常”仅处理您可以处理的异常。为了不显示黄色屏幕,我个人更喜欢在global.asax事件应用程序中捕获未损坏的异常\u error在应用程序的顶层捕获系统异常也不是一个好的做法()。你为什么要这么做?-1:这太过分了。当然,当线程是最合适的选项时,我们应该直接使用它。我强烈建议您使用线程池。因此,请使用线程池(由Task
和BackgroundWorker
使用),而不是创建自己的线程。@Aliostad:new thread
和ThreadPool.QueueUserWorkItem之间在概念上有什么区别吗