[英]Why is catching “Exception” not ambiguous when I have System.Exception and MyNamespace.Exception?
[英]Catching System.Exception in thread
我知道,除非在应用程序的顶层,否则捕获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();
}
}
这取决于线程正在执行的操作以及应用程序中线程的上下文。 一般来说,您应该遵循经验法则: 除非您知道如何处理异常,否则不要捕获异常 。 (我正在简化,但这是经验法则)。
由于我们在谈论System.Exception
而不是某些子类,因此我假设您实际上并不知道如何处理该异常。 记录错误,并让应用程序终止(唯一正当理由赶你不能处理的除外) 可以做到在不脱离提出它的线程内捕捉异常,所以简单的答案是否定的,这是没有确定 。
如果我没有记错的话,.NET 1实际上捕获并吞噬了后台线程引发的所有异常。 这导致在写的不好的程序这么多的问题,MS改变行为在.NET 2让异常崩溃的应用程序-你能想象他们有很好的理由作出这样的重大更改。
关于BackgroundWorker
更新:
请不要将BackgroundWorker
的使用模式误认为是“吞下System.Exception
是可以的”。 这是BackgroundWorker.RunWorkerCompleted
的文档所说的:
在访问RunWorkerCompletedEventArgs.Result属性之前,您的RunWorkerCompleted事件处理程序应始终检查AsyncCompletedEventArgs.Error和AsyncCompletedEventArgs.Cancelled属性。 如果引发了异常或操作被取消,则访问RunWorkerCompletedEventArgs.Result属性将引发异常。
简单地说, 选择忽略此建议或故意忽略返回值 (否则仍会引发异常!)是不好的编程习惯。
是的-这是个好主意:)
嗯,我看不出为什么有人建议捕获顶级异常不是一个好主意。 说真的,你没抓住他们吗?
从实际的日常开发角度来看,如果您的后台线程有顶级异常,则您想了解一下。 您不希望应用程序崩溃,这是默认行为-令人惊讶的是,用户不喜欢该应用程序。 这是您肯定想捕获异常并记录/恢复的少数几个地方之一。
从官方上讲,这不是一个好习惯,但有时确实可以做到。
参数与在“主”线程上执行此操作的参数完全相同。
一个主要的问题是,如果您吞下了这样的错误,则您的应用程序可能会非常不正确地运行-例如,它可能会覆盖关键的用户数据-而不是终止。
如果您确实选择了这条路线,则可能要小心,将ThreadAbortException
从捕获中排除-如果有人中止了工作线程,则这是“预期的异常”(在您的应用程序中可能是,也可能不是)
只处理异常,您可以做一些事情。 为了不显示黄色屏幕,我个人更喜欢在global.asax事件Application_error中捕获不必要的异常
因此,如果确实在UI中使用new Thread()
,那将是令人头疼的。
鼓励使用BackgroundWorker
或Task<T>
封装线程异常处理,因此就catch
块而言无需进行异常处理。
如果您想要自己的线程(从CLR通过C# ),这是四种可接受的情况:
我强烈建议您尽可能使用线程池执行异步计算绑定操作。 但是,在某些情况下,您可能想显式创建专门用于执行特定计算绑定操作的线程。 通常,如果要执行要求线程处于线程池线程不正常的特定状态的代码,则需要创建一个专用线程。 例如,如果我希望线程以特殊优先级运行(所有线程池线程均以正常优先级运行,并且您不应更改线程池线程的优先级),则可以创建一个专用线程。 如果我想使该线程成为前台线程(所有线程池线程均为后台线程),我也将考虑创建和使用自己的线程,从而防止应用程序在线程完成其任务之前死亡。 如果计算绑定任务非常长时间运行,我还将使用专用线程。 这样,当线程池试图找出是否要创建一个额外的线程时,我就不会对线程池的逻辑费劲。 最后,如果我想启动一个线程并可能通过调用Thread的Abort方法(在第21章“ CLR托管和AppDomains”中讨论)过早中止该线程,则将使用专用线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.