【问题标题】:Cannot catch System.Reflection.TargetInvocationException (using TPL)无法捕获 System.Reflection.TargetInvocationException(使用 TPL)
【发布时间】:2012-11-12 18:14:27
【问题描述】:

我有一个具有以下结构的匿名 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 块(在我的原始代码 sn-p 中)没有捕获它。

由于我无法捕捉到异常,它最终导致应用程序崩溃。

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

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

更新:

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

【问题讨论】:

  • 您的DoStuff 电话中有什么内容?也许 Sprint.NET 的实现是在一个完全独立的线程中打开它?

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


【解决方案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 了解异常处理和任务。

【讨论】:

  • 但我不调用 task.Wait(),我也不希望调用。在我的 DoStuff() 方法中,我等待其他异步任务完成。在调试器下运行时,抛出此异常时,我永远不会从 DoStuff() 方法返回。
猜你喜欢
  • 2017-02-18
  • 2021-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-27
  • 2023-02-04
  • 1970-01-01
相关资源
最近更新 更多