繁体   English   中英

在线程中捕获System.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() ,那将是令人头疼的。

鼓励使用BackgroundWorkerTask<T>封装线程异常处理,因此就catch块而言无需进行异常处理。


如果您想要自己的线程(从CLR通过C# ),这是四种可接受的情况:

我强烈建议您尽可能使用线程池执行异步计算绑定操作。 但是,在某些情况下,您可能想显式创建专门用于执行特定计算绑定操作的线程。 通常,如果要执行要求线程处于线程池线程不正常的特定状态的代码,则需要创建一个专用线程。 例如,如果我希望线程以特殊优先级运行(所有线程池线程均以正常优先级运行,并且您不应更改线程池线程的优先级),则可以创建一个专用线程。 如果我想使该线程成为前台线程(所有线程池线程均为后台线程),我也将考虑创建和使用自己的线程,从而防止应用程序在线程完成其任务之前死亡。 如果计算绑定任务非常长时间运行,我还将使用专用线程。 这样,当线程池试图找出是否要创建一个额外的线程时,我就不会对线程池的逻辑费劲。 最后,如果我想启动一个线程并可能通过调用Thread的Abort方法(在第21章“ CLR托管和AppDomains”中讨论)过早中止该线程,则将使用专用线程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM