liorblob
liorblob

Reputation: 537

Catch and propagate exceptions in async methods

I have the following code in a while loop:

Task worker = 
    Task.Factory
        .StartNew(() => 
            {
                ProduceAsync(param, tokenSource.Token);
            }, tokenSource.Token)
        .ContinueWith((t) => 
            { 
                OnException(t); 
            }, TaskContinuationOptions.OnlyOnFaulted);

ProduceAsync looks like this:

private async Task ProduceAsync( List<string> param, CancellationToken token)
{
    token.ThrowIfCancellationRequested();
    var task = _requestManager.GetProductsAsync(param);
    var products;
    try
    {
        products = await task;
       _products.Add(products);
    }
    catch
    {
        task.GetAwaiter().GetResult();
    }
}

When there's an exception inside the async request I would like the program to fail fast, so on OnException(t) I'm cancelling the tasks using tokenSource. The problem here that ProduceAsync does not propagate the exception and OnException isn't being called. How can I get it to propagate the exception?

Note: I copied the code by hand to my phone so there might be compilation errors...

Upvotes: 0

Views: 331

Answers (1)

Meirion Hughes
Meirion Hughes

Reputation: 26438

I'm reasonably sure that instead of

Task.Factory.StartNew(() =>  { 
   ProduceAsync(param, tokenSource.Token);
}, tokenSource.Token)
.ContinueWith(...

you should be doing:

Task.Run(async () =>  { 
   await ProduceAsync(param, tokenSource.Token);
}, tokenSource.Token)
.ContinueWith(...

basically if you don't wait for your async method to complete then it will run separately and the delegate you pass to Task.Factory.StartNew will return immediately. Also you should use Task.Run as its a bit safer.

Also, you may want to do a rethrow with throw in your catch block after you do whatever you want with the exception.

Upvotes: 2

Related Questions