开发者

using block swallowing exceptions

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 excep开发者_Go百科tion and that's what I'm trying to handle in one common place.

Thanks,


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.


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.


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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜