2
votes

I have an anonymous TPL task with the following structure:

   Task.Factory.StartNew(() =>
        {
            try
            {
                DoStuff();
            }
            catch (OperationCanceledException ex)
            {
                // process cancellation
            }
            catch (Exception ex)
            {
                // process (log) all exceptions
            }
            finally
            {
                // tie up various loose ends
            }
        },
            myCancellationToken, // cancellation token
            TaskCreationOptions.LongRunning, // always create a new thread
            TaskScheduler.Default // default task scheduler
        );

Inside of the DoStuff() function, I'm using Spring.NET Social extension for Dropbox to upload a large file to Dropbox. For some reason that I don't yet understand, an exception is being generating during the file upload (via the UploadFileAsync() method call):

(System.Net.Sockets.SocketException (0x80004005): An established connection was aborted by the software in your host machine).

I'm still working out why this exception is happening, but that's not the part that concerns me a present. The bigger problem is that the exception is ultimately wrapped by System.Reflection.TargetInvocationException and for some strange reason, my try/catch block (in my original code snippet) isn't catching it.

Since I cannot catch the exception, it ultimately crashes the app.

Although I didn't think it should be necessary, I even tried adding an explicit catch block for TargetInvocationException, but again it never fires.

So my question is - how I do I catch this exception, and why isn't it being caught by the constructs shown in my code above?

UPDATE:

This problem appears to have nothing to do with the TPL after all. I modified the call to remove the call to StartNew() so that the code executes synchronously, and I still cannot catch this exception.

1
What's in your DoStuff call? Perhaps Sprint.NET's implementation is opening it in an entirely separate thread? - Chris Sinclair

1 Answers

1
votes

I used this code to verify that the TargetInvocationException can be caught:

[Test]
public void TaskExceptionTest()
{

    var task = Task.Factory.StartNew(
        () =>
        {
            try
            {
                throw new TargetInvocationException(null);
            }
            catch (Exception e)
            {
                Console.WriteLine("Caught one (inside):" + e.GetType().Name);
            }
        });
    try
    {
        task.Wait();
    }
    catch (AggregateException ae)
    {
        // Assume we know what's going on with this particular exception. 
        // Rethrow anything else. AggregateException.Handle provides 
        // another way to express this. See later example. 
        foreach (var e in ae.InnerExceptions)
        {
            if (e is TargetInvocationException)
            {
                Console.WriteLine("After:" + e.GetType().Name);
            }
            else
            {
                throw;
            }
        }
    }
}

You can read here about exception handling and tasks.