我知道捕获System.Exception不是好习惯,除非在应用程序的顶层。线程怎么样?可以在线程的顶层捕获System.Exception吗?
更新 该线程是一个长时间运行的线程,只应在应用程序停止时终止。因此,为了确保应用程序不会崩溃,我只需捕获System.Exception并记录错误。一切都重新创造。
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();
}
}
答案 0 :(得分:3)
这取决于线程正在做什么以及应用程序中线程的上下文。一般来说,你应该遵循黄金法则:除非你知道如何处理它,否则不会发现异常。 (我当然正在简化,但这是一个经验法则。)
由于我们讨论的是System.Exception
而不是某些子类,我假设您实际上并不知道如何处理异常。记录错误并让应用程序终止(捕获无法处理的异常的唯一合理理由)can be done而不从引发它的线程中捕获异常,所以简短的答案是否,没关系。
如果我没记错的话,.NET 1实际上已经捕获并吞噬了后台线程上引发的所有异常。这导致了编写错误的程序中的许多问题,MS改变了.NET 2中的行为,让异常使应用程序崩溃 - 你可以想象他们非常有充分的理由做出如此突破性的改变
关于BackgroundWorker
的更新:
请不要将BackgroundWorker
的使用模式误认为“吞咽System.Exception
正常”。以下是BackgroundWorker.RunWorkerCompleted
的文档所说的内容:
您的RunWorkerCompleted事件处理程序 应该经常检查 AsyncCompletedEventArgs.Error和 AsyncCompletedEventArgs.Cancelled 访问之前的属性 RunWorkerCompletedEventArgs.Result 属性。如果引发异常 或者如果操作被取消, 访问 RunWorkerCompletedEventArgs.Result 财产引起了例外。
选择忽略这个建议或忽略故意返回值(否则仍然会抛出异常!)简单地说是糟糕的编程习惯。
答案 1 :(得分:2)
是的 - 这是一个很好的主意:)
嗯,我不明白为什么人们建议抓住顶级例外不是一个好主意。说真的,你没有抓住它们?从实际的日常开发角度来看,如果您的后台线程有顶级异常,那么您希望了解它。您不希望应用程序崩溃,默认行为 - 用户不喜欢这样,令人惊讶。这是您绝对想要捕获异常和记录/恢复的少数几个地方之一。
答案 2 :(得分:0)
官方说这不是好习惯,但有时它已经完成了。
参数与在“主”线程上执行此操作完全相同。
一个主要问题是如果您吞下这样的错误,那么您的应用程序可能会非常错误地运行 - 例如它可能会覆盖关键的用户数据 - 而不是终止。
如果您确实选择了这条路线,您可能需要小心将ThreadAbortException
排除在捕获之外 - 如果有人中止工作线程(这可能是也可能不是),这是一个“预期的异常”在您的应用程序中的情况)
答案 3 :(得分:0)
只处理你可以做的事情。为了不显示黄色屏幕,我个人更喜欢在global.asax事件中捕获unhandeld excetpion Application_error
答案 4 :(得分:-2)
因此,如果你确实在UI中使用new Thread()
,那就不赞成了。
鼓励使用BackgroundWorker
或Task<T>
封装线程异常处理,因此不需要在catch
块方面处理异常。
这4种情况是您需要自己的线程(来自CLR via C#):
的可接受情况我强烈建议您使用 线程池执行异步 计算绑定操作 可能。但是,有一些 你可能想要的场合 显式创建一个专用的线程 执行特定的 计算绑定操作。通常情况下, 你想要创建一个专门的 线程,如果你要执行代码 这需要线程在一个 特殊状态不正常 用于线程池线程。例如, 如果我,我会创建一个专用线程 希望线程在特殊情况下运行 优先级(所有线程池线程都运行 在正常的优先级,你不应该 改变一个线程池线程 优先)。我也会考虑 如果我,创建和使用我自己的线程 想让线程成为前景 线程(所有线程池线程都是 因此,背景线程) 防止应用程序死亡 直到我的线程完成了它 任务。我也使用专用线程 如果计算绑定任务是 极长的跑步;这样,我 不会对线程池征税 它试图找出逻辑 是否要创建一个额外的 线。最后,我会使用专用的 线程,如果我想启动一个线程 并可能过早地中止它 调用Thread的Abort方法 (在第21章“CLR托管”中讨论过 和AppDomains“)。