Async exception handling with void
I'm using Async CTP to write an IO heavy console app. But I'm having problems with exceptions.
public static void Main()
{
while (true) {
try{
myobj.DoSomething(null);
}
catch(Exception){}
Console.Write("done");
//...
}
}
//...
public async void DoSomething(string p)
{
if (p==null) throw new InvalidOperationException();
else await SomeAsyncMethod();
}
And the following happens: "done" gets written to the console, then I get the exception in the 开发者_如何转开发debugger, then I press continue my program exists.
What gives?If you give your Console application an async-compatible context (e.g., AsyncContext
(docs, source) from my AsyncEx library), then you can catch exceptions that propogate out of that context, even from async void
methods:
public static void Main()
{
try
{
AsyncContext.Run(() => myobj.DoSomething(null));
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
Console.Write("done");
}
public async void DoSomething(string p)
{
if (p==null) throw new InvalidOperationException();
else await SomeAsyncMethod();
}
When you call DoSomething()
it basically creates a Task
under the hood and starts that Task
. Since you had a void
signature, there is no Task
object to signal back or that you could have blocked on, so execution fell straight through to done. Meanwhile the task throws an exception, which nobody is catching, which, I suspect, is why your program terminates.
I think the behavior you wanted is more like this:
public static void Main()
{
while (true) {
var t = myobj.DoSomething(null);
t.Wait();
if(t.HasException) {
break;
}
}
Console.Write("done");
//...
}
}
//...
public async Task DoSomething(string p)
{
if (p==null) throw new InvalidOperationException();
else await SomeAsyncMethod();
}
This will block on each DoSomething
until it's done and exit the loop if DoSomething
threw. Of course, then you are not really doing anything async. But from the pseudo code, i can't quite tell what you wanted to happen asynchronously.
Main take-away: Using void
for an async method means that you loose the ability to get the exception unless you are await
ing that async method. As a sync call it basically just schedules work and the outcome disappears into the ether.
精彩评论