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
精彩评论