Max_dev
Max_dev

Reputation: 508

Handling exception occured inside Task.ContiueWith

I am working on wpf and i have written the below code to display exception when they occured while fetching data from web service.

Two action methods are there, 1st is to call remote service and second to update UI object when it got the result.

I am getting exception box properly when exception occured during First action(intial), but when exception occurred in second action(success) they are ignored and nothing happed. Event breakpoint doesn't hit at last line of continue with .

I like to know what is happening and best possible solution. Can't this type of exception handled globally?

private void ExecuteSafely(string message, Action intial, Action successAction)
{

    var task = Task.Factory.StartNew(intial);
    task.ContinueWith(t =>
    {
        if (t.Exception != null)
        {
            HandleException(t.Exception);
        }
        else
        {
            successAction.Invoke();
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

Upvotes: 1

Views: 120

Answers (2)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149518

but when exception occurred in second action(success) they are ignored and nothing happens

Because you aren't wrapping your code in a try-catch block, hence the exception isn't handled and is swallowed by your continuation task.

To catch it, do the wrapping:

private void ExecuteSafely(string message, Action initial, Action successAction)
{
    var task = Task.Factory.StartNew(initial).ContinueWith(t =>
    {
        if (t.Exception != null)
        {
            HandleException(t.Exception);
        }
        else
        {
            try
            {
               successAction();
            }
            catch (Exception e)
            { 
                // Handle your exception.
            }
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

If you're using .NET 4.0, the exception swallowed will eventually be thrown during the finalization of the Task.

If you're using using .NET 4.5, async-await will be less verbose:

private async Task ExecuteSafelyAsync(string message, 
                                      Action initial, 
                                      Action successAction)
{
    try
    {
        var task = await Task.Run(initial);
        successAction();
    }
    catch (Exception e)
    {
        // You get here if either Task.Run or successAction throws
    }
}

And when you invoke it:

await ExecuteSafelyAsync("hello", initial, success);    

Upvotes: 2

Cologler
Cologler

Reputation: 724

When successAction throw a Exception, UI thread can not catch Exception because of successAction was not be invoke on UI thread.

If you working on .net 4.5, I think you should use async/await, like:

private async void ExecuteSafely(string message, Action intial, Action successAction)
{
    try
    {
        await Task.Factory.StartNew(intial);
        successAction.Invoke();
    }
    catch (Exception e)
    {
        HandleException(e);
    }
}

Upvotes: 0

Related Questions