somehow my exceptions seem to being caught by method they are executing in. Here is the code to call the method. As you can see I create a cancellation token with a time out. I register a method to call when the cancellation token fires and then I start a new task. The cancellation token appears to be working OK. As does the registered method.
var cancellationToken = new CancellationTokenSource(subscriber.TimeToExpire).Token;
cancellationToken.Register(() =>
{
subscriber.Abort();
});
var task = Task<bool>.Factory.StartNew(() =>
{
subscriber.RunAsync((T)messagePacket.Body, cancellationToken);
return true;
})
.ContinueWith(anticedant =>
{
if (anticedant.IsCanceled)
{
Counter.Increment(12);
Trace.WriteLine("Request was canceled");
}
if (anticedant.IsFaulted)
{
Counter.Increment(13);
Trace.WriteLine("Request was canceled");
}
if (anticedant.IsCompleted)
{
Counter.Increment(14);
}
The next piece of code is the method that seems to be not only throwing the excetion (expected behavior. but also catching the exception.
public async override Task<bool> ProcessAsync(Message input, CancellationToken cancellationToken)
{
Random r = new Random();
Thread.Sleep(r.Next(90, 110));
cancellationToken.ThrowIfCancellationRequested();
return await DoSomethingAsync(input);
}
The exception is being thrown by the cancellation token but according to intellitrace it is being caught at the end of the method. I have tried a number of different options including throwing my own exception, but no matter what the continuewith function always executes the IsComleted or ran to completion code.
Any ideas on what I am doing wrong?
Thanks
I assume that
RunAsyncis the same asProcessAsync.Yup. Any
asyncmethod will catch its own exceptions and place them on its returnedTask. This is by design.Well, let’s take another look at the code:
Consider the lambda passed to
StartNew: it callsRunAsync, it ignores theTaskthat it returns, and then it returnstrue(successfully). So theTaskreturned byStartNewwill always return successfully. This is why theContinueWithalways executes for a successfully-completed task.What you really want is to
awaittheTaskreturned byRunAsync. So, something like this:You’re still ignoring the return value of
RunAsync(theboolit returns is ignored), but you’re not ignoring theTaskitself (including cancellation/exception information).P.S. I’m assuming there’s a lot of code you’re not showing us; using
StartNew/Runto just kick off some async work and return a value is very expensive.P.P.S. Use
await Task.Delayinstead ofThread.Sleep.