Catching an Exception across treeview.Nodes.Add / treeview_AfterSelect event boundary
There is a place in my WinForms program that throws a MyOwnException.
void CodeThatThrowsMyOwnException()
{
...
throw new MyOwnException("Deep Inside");
...
}
Further up the stack, there is a simple try/catch block
try
{
CodeThatThrowsMyOwnException();
}
catch (MyOwnException moe)
{
MessageBox.Show("Hit this point in the code! Hurray!");
}
MessageBox.Show("Later, alligator.");
On a colleague's computer (running VS 2008 SP1 like me) the dialog box shows up. On my computer, it never catches the exception nor shows the dialog box. When I place a breakpoint deep inside the code (CodeThatThrowsMyOwnException) on the line that throws the Exception, it hits the breakpoint on the line. If I press F5 (Debug > Run) it skips passed my catch block and displays the "Later, alligator" message.
Actually pasting the "void CodeThatThrowsMyOwnException() { throw new MyOwnException("Shallow"); }" code into my code (instead of calling my real code) and literally calling "CodeThatThrowsMyOwnException();" in the try block does however get show the message in the catch block.
As far as I can tell, I am not creating any threads and I have looked for try {} catch {} blocks that catch all exceptions but cannot find any in the involved projects (and if they were in there, why would this catch block still work on my colleague's machine?)
Strangely enough running my code by double clicking the executable gives me an unhandled exception on my machine and the same on my colleague's machine. This is a clue that led me to try the following:
When I place a breakpoint at the throw MyOwnException("Deep Inside") line deep inside my code, the call stack contains a line "[External Code]" between my exception handler and the place where I call 'throw MyOwnException("Deep Inside")'. If I put a try/catch MyOwnException block further away from the throw (but on this side of the [External Code] I can still catch the exception, anywhere I place the try catch block (around relevant parts of the function chain):
try
{
CodeChain(...);
}
catch (DrawException de)
{
MessageBox.Show("Hurray!"); // being executed, but only on the 'throw' side of the [External Code] part of the call stack
}
However, when I step outside (below on the stack) the [External Code], the exception does not fire. This is unexpected:
try
{
treeview.Nodes.Add(treeNode); // triggers the aforementioned chain of code with MyOwnException thrown
}
catch (DrawException de) // no matter what I do, this will not handle my cursed MyOwnException
{
MessageBox.Show("Hurray!"); // not being executed
}
This is the heart of my problem: I can't move my catch up the call stack because I need to run lots of tests (see below).
I have a sort of hypothesis, which is that his debugger is magically lifting the exception across thread boundaries (or across external code, i.e. Windows GUI events) in his debugger, whereas in the other three situations (my debugger (without the 64 bit extensions) and also when either machine runs the EXE from windows explorer the exception) the exception is truly unhandled on that thread.
So how do I catch this exception? Re开发者_StackOverflow中文版-engineer my whole system to avoid using treeview.AfterSelect? Clearly I don't understand the limitations of exceptions.
Potential problem?
- I have a delegate in there to keep my system modular and reusable. Can exceptions be thrown "through" a delegate, across module boundaries?
What I'm trying to accomplish (Testing Harness) and why I need Exceptions
I'm using this in an automated test harness. I need to fix some really tough logical/algorithmic bugs in a complicated GUI system by replaying action scripts (text files) that find these exceptional circumstances and narrow the problem down. (There is probably no good workaround to this in my program, in terms of rewriting or refactoring the design: I need to catch these Exceptions in this QA phase, fix the bugs (tough algorithmic special cases) before I ship so I don't subject my users to such buggy software. It's not like I'm using exceptions for exotic control flow for for fun (cf. Int32.Parse).)
The treeview_AfterSelect is going to be called most of the time by what you're referring to as [External Code]. These will be the result of the user selecting a node or even when the form is loading and you're adding nodes (which I suspect might be happening on your unhandled exception).
If your AfterSelect handler is going to throw exceptions for some reason, you cannot rely on your calling code to handle those exceptions. Otherwise, any other way that AfterSelect gets called could result in an unhandled exception.
精彩评论