debugger reports an handled exception as unhandled - in async methods

  • Thread starter Thread starter Marcel Overweel
  • Start date Start date
M

Marcel Overweel

Hi,

I've got a problem with exception handling when using async methods.
Actually, the code seems to runs fine, but the debugger reports that an
exception is not handled by user code, while in fact it is handled properly.

Basicly, I start a method using a delegate's BeginInvoke().
In this method, an exception is raised.
In the callback methode, I catch this exception and store it in a variable
of a custom asyncresult object.

This whole is wrapped in a set of Begin/CallBack/End methods which
uses this custom asyncresult object to return the result of the process.

It is difficult for me to just explaining the details,
so here is the code, excluding irrelevant details:

* Code of the class containing the async agony:

// This method is called using a delegate.BeginInvoke (see below)
protected BasicReturnCode DoPing()
{
.. some irrelevant code ..
BasicReturnCode res = DoSomeWork();
.. some irrelevant code ..
return res;
}

private BasicReturnCode DoSomeWork()
{
.. Here, some work is done and a
.. TimeoutException can be thrown.
. <-- Exception is thrown here at the end of the method
} <-- Here the debugger reports the following:

"TimeoutException was unhandled by user code"


private delegate BasicReturnCode PingDelegate();

// The caller will call this method to start the ascyn operation:

public IAsyncResult BeginPing(
AsyncCallback userCallback, Object stateObject)
{
AsyncResult<BasicReturnCode> ar =
new AsyncResult<BasicReturnCode>(userCallback, stateObject);
PingDelegate d = new PingDelegate(this.DoPing);

IAsyncResult i_ar = d.BeginInvoke(
new AsyncCallback(this.PingCallback), ar);

return ar;
}


public BasicReturnCode EndPing(IAsyncResult asyncResult)
{
return ((AsyncResult<BasicReturnCode>)asyncResult).EndInvoke();
}


protected void PingCallback(IAsyncResult i_ar)
{
Exception ex_return = null;
BasicReturnCode ret = null;

try
{
ret = ((PingDelegate)
((AsyncResult)i_ar).AsyncDelegate).EndInvoke(i_ar);
}
catch (TimeoutException ex) <-- Exception IS catched AFTER the
debugger reported that is was unhandled!
{
ex_return = ex; // Time-out during communication.
}

AsyncResult<BasicReturnCode> ar =
(AsyncResult<BasicReturnCode>)(i_ar.AsyncState);

if (ex_return == null)
ar.SetAsCompleted(ret, false);
else
ar.SetAsCompleted(ex_return, false);
}


* Code on the calling Form:

private void buttonPing_Click(object sender, EventArgs e)
{
Terminal t = new Terminal(.. some parameters ..);
t.BeginPing(this.OnPingComplete, t);
}

private void OnPingComplete(IAsyncResult ar)
{
Terminal t = ((Terminal)ar.AsyncState);
try
{
BasicReturnCode r = t.EndPing(ar);
.. show result ..
}
catch (TimeoutException ex) // Timeout during communication
{
.. show exception .. <-- This is performed, so it IS handled
}
}


Note that all code is in the same assembly except for the calling code
(the buttonPing_Click and OnPingComplete).
And all code is user code.

So why do I get that message from the debugger?
If it's just an annoying message, I can live with it.
But this means I've made some structural error, I do not want to
release it to our clients.

Also, I don't want to disable the catching of these exceptions becuase
I do want to know it when I don't catch it myself.

regards,
Marcel
 
Marcel said:
Hi,

I've got a problem with exception handling when using async methods.
Actually, the code seems to runs fine, but the debugger reports that an
exception is not handled by user code, while in fact it is handled properly.

Basicly, I start a method using a delegate's BeginInvoke().
In this method, an exception is raised.
In the callback methode, I catch this exception and store it in a variable
of a custom asyncresult object.

[...]
So why do I get that message from the debugger?

Because that's exactly what happened. When the exception was actually
thrown, the first exception handler that is executed is not in your user
code. It's in the asynchronous delegate execution code in .NET. After
all, how would your callback get called unless some .NET code knows that
your delegate method is done executing, unless some other code caught
that exception?

You don't get to see the exception until you call EndInvoke(), which you
didn't do until _after_ your callback was called, so you necessarily
have no way to see the exception until after .NET's already had a chance
to handle it.

When the exception is first thrown, .NET catches it, saves the exception
information so it can be presented again later during the EndInvoke()
method, and then calls your callback method. When your code actually
gets to catch it, the exception is being thrown for the second time.
If it's just an annoying message, I can live with it.

I don't know why it's annoying for the debugger to truthfully tell you
exactly what happened, but yes...if you find it annoying, you'll have to
live with it. :)

Pete
 
Peter Duniho said:
Marcel said:
Hi,

I've got a problem with exception handling when using async methods.
Actually, the code seems to runs fine, but the debugger reports that an
exception is not handled by user code, while in fact it is handled
properly.

Basicly, I start a method using a delegate's BeginInvoke().
In this method, an exception is raised.
In the callback methode, I catch this exception and store it in a
variable
of a custom asyncresult object.

[...]
So why do I get that message from the debugger?

Because that's exactly what happened. When the exception was actually
thrown, the first exception handler that is executed is not in your user
code. It's in the asynchronous delegate execution code in .NET. After
all, how would your callback get called unless some .NET code knows that
your delegate method is done executing, unless some other code caught that
exception?

Good point.
You don't get to see the exception until you call EndInvoke(), which you
didn't do until _after_ your callback was called, so you necessarily have
no way to see the exception until after .NET's already had a chance to
handle it.

When the exception is first thrown, .NET catches it, saves the exception
information so it can be presented again later during the EndInvoke()
method, and then calls your callback method. When your code actually gets
to catch it, the exception is being thrown for the second time.


I don't know why it's annoying for the debugger to truthfully tell you
exactly what happened, but yes...if you find it annoying, you'll have to
live with it. :)

Pete

Thanks for the clarification Pete.

regards,
Marcel
 
Back
Top