使用块吞咽异常

发布于 2024-11-17 00:40:04 字数 1432 浏览 1 评论 0原文

我已经

void foo1()
{
   using(...){...}
}

void foo2()
{
   using(...){...}
}

void foo3()
{
   using(...){...}
}

并且

void foo()
{
    ...
    backgroundWorker.DoWork += (s, ev) =>
                                           {
                                               try
                                               {
                                                   foo1();
                                                   foo2();
                                                   foo3();
                                               }
                                               catch (Exception ex)
                                               {
                                                   // log ex
                                               }
                                           };
      ...    
}

我刚刚读过 使用< /a> 阻止吞咽异常。它有一种优雅的方式来处理 foo() 中的 foo1()foo2()foo3() 异常代码>.我不想希望在方法中的每个using块内都有一个try/catch。我确实偶然发现了这篇文章,其中一个扩展建议方法,但我只是检查是否有更好的方法。

仅供参考,网络断开会导致 using 块内的逻辑抛出异常,这就是我试图在一个常见位置处理的问题。

谢谢,

I have

void foo1()
{
   using(...){...}
}

void foo2()
{
   using(...){...}
}

void foo3()
{
   using(...){...}
}

and I have

void foo()
{
    ...
    backgroundWorker.DoWork += (s, ev) =>
                                           {
                                               try
                                               {
                                                   foo1();
                                                   foo2();
                                                   foo3();
                                               }
                                               catch (Exception ex)
                                               {
                                                   // log ex
                                               }
                                           };
      ...    
}

and I just read that using blocks swallow exceptions. It there an elegant way to handle exceptions from foo1(), foo2() and foo3() in foo(). I don't want to have a try/catch inside of each using block in the methods. I did stumble into this post where an extension method is suggested but I'm just checking to see if there is anything better.

FYI, Network disconnection causes the logic inside the using block to throw an exception and that's what I'm trying to handle in one common place.

Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云胡 2024-11-24 00:40:04

我想我理解这种困惑。这是一些伪代码(它实际上可能会执行?)更简单地解释您的场景:

public class Foo
{
    public void DoStuff()
    {
        using (var x = new Thing())
        {
            throw new ApplicationException("This code breaks");
        }
    }

    private class Thing : IDisposable
    {
        public override Dispose()
        {
            throw new ApplicationException("Help, I can't dispose!");
        }
    }
}

可以将这段代码视为与此代码相同:

public class Foo
{
    public void DoStuff()
    {
        var x = new Thing();
        try
        {
            throw new ApplicationException("This code breaks");
            x.Dispose();
        }
        catch (Exception err)
        {
            x.Dispose();
            rethrow;
        }
    }

    private class Thing : IDisposable
    {
        public override Dispose()
        {
            throw new ApplicationException("Help, I can't dispose!");
        }
    }
}

通过使用 using 块,您本质上是在说:“无论您做什么,请在继续之前对此对象执行 Dispose()。”但是,using 块无法妥善处理 Dispose() 失败的情况。因此,它永远不会抛出内部异常,因为有另一个异常抢占了它,即使它是在之后发生的。

这有道理吗?我什至回答了你的问题吗?我不确定您是否正在寻求帮助来理解这一点或什么。

I think I understand the confusion. Here's some pseudo-code (it may actually execute?) explaining your scenario more simply:

public class Foo
{
    public void DoStuff()
    {
        using (var x = new Thing())
        {
            throw new ApplicationException("This code breaks");
        }
    }

    private class Thing : IDisposable
    {
        public override Dispose()
        {
            throw new ApplicationException("Help, I can't dispose!");
        }
    }
}

This code can be thought of as the same as this code:

public class Foo
{
    public void DoStuff()
    {
        var x = new Thing();
        try
        {
            throw new ApplicationException("This code breaks");
            x.Dispose();
        }
        catch (Exception err)
        {
            x.Dispose();
            rethrow;
        }
    }

    private class Thing : IDisposable
    {
        public override Dispose()
        {
            throw new ApplicationException("Help, I can't dispose!");
        }
    }
}

By using a using block, you are essentially saying, "No matter what you do, execute Dispose() on this object before moving on." However, the using block doesn't gracefully handle the case when Dispose() fails. Because of this, it never gets around to throwing the inside exception because there was another exception that pre-empted it, even if it occurred afterwards.

Does this make sense? Did I even answer your question? I'm not sure if you're looking for help understanding this or what.

_失温 2024-11-24 00:40:04

我担心 Microsoft 会陷入与 WCF 相同的困境。

请参阅避免使用语句出现问题

也许他们应该遵循自己的指南< /a>.

在几乎所有(其他)情况下,using 块都是最佳实践。

My fear is that Microsoft went down the same rabbit hole here as they did with WCF.

See Avoiding Problems with the Using Statement.

Maybe they should follow their own guidelines.

In almost every (other) case a using block is a best practice.

就是爱搞怪 2024-11-24 00:40:04

您可以尝试此代码来从 using 语句中冒泡和异常

Exception exc = null;
using (var x = new object())
{
    try
    {
       // do something x, that causes an exception to be thrown
    }
    catch(Exception ex) { exc = ex; } // bubble-up the exception
 }
 if(exc != null) { throw exc; } // throw the exception if it is not null

Youcan try this code to bubble-up and exception from a using statement

Exception exc = null;
using (var x = new object())
{
    try
    {
       // do something x, that causes an exception to be thrown
    }
    catch(Exception ex) { exc = ex; } // bubble-up the exception
 }
 if(exc != null) { throw exc; } // throw the exception if it is not null
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文