无法捕获System.Reflection.TargetInvocationException(使用TPL)

时间:2012-11-12 18:14:27

标签: c# .net task-parallel-library spring.net

我有一个具有以下结构的匿名TPL任务:

   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
        );

在DoStuff()函数内部,我使用Spring.NET Social extension for Dropbox将大文件上传到Dropbox。由于某种原因我还不明白,在文件上传过程中会产生异常(通过UploadFileAsync()方法调用):

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

我仍然在研究为什么会发生这种异常,但这不是我关注礼物的部分。更大的问题是异常最终被包裹起来 System.Reflection.TargetInvocationException和一些奇怪的原因,我的try / catch块(在我的原始代码片段中)没有捕获它。

由于我无法捕获异常,它最终会崩溃应用程序。

虽然我认为没有必要,但我甚至尝试为TargetInvocationException添加一个显式的catch块,但它再也不会触发。

所以我的问题是 - 如何捕获此异常,为什么它不会被上面代码中显示的构造捕获?

更新

这个问题似乎与TPL无关。我修改了调用以删除对StartNew()的调用,以便代码同步执行,我仍然无法捕获此异常。

1 个答案:

答案 0 :(得分:1)

我使用此代码验证是否可以捕获TargetInvocationException:

[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;
            }
        }
    }
}

您可以阅读有关异常处理和任务的here