【问题标题】:Unable to catch an Exception from Task.Run无法从 Task.Run 捕获异常
【发布时间】:2016-10-25 03:34:06
【问题描述】:

我正在关注这个MSDN guide 来处理任务中的异常。

这是我写的:

var myTask = Task.Run(() =>
    {
        throw new Exception("test");
    });
try
{
    myTask.Wait();
}
catch (Exception e)
{
    return false;
}

我在catch 块中设置了一个断点,但是在调试运行时,代码没有到达断点,它给了我:

用户代码未处理异常

我不知道发生了什么,因为我非常关注 MSDN 指南中的示例。事实上,我将示例复制到我的项目中,它仍然给出了同样的问题。

有什么方法可以处理任务之外的异常吗?如果任务抛出任何异常,我需要根据事实返回一个布尔值。

编辑

为了让你们中的一些人更清楚,这是一组更完整的代码:

public bool ConnectToService()
{
    try
    {
        // Codes for ServiceHost etc etc, which I'm skipping
        // These codes are already commented out for this test, so they do nothing

        var myTask = Task.Run(() =>
            {
                // Supposed to connect to a WCF service, but just throwing a test exception now to simulate what happens when the service is not running
                throw new Exception("test");
            });
        try
        {
            myTask.Wait();
        }
        catch (Exception e)
        {
            return false;
        }

        return true;
    }

    catch (Exception)
    {
        return false;
    }
}

来电者:

public void DoSomething()
{
    try
    {
        // Other irrelevant stuff
        if (ConnectToService())
        {
            DoAnotherThing();
        }
    }
    catch (Exception)
    {
    }

}

我还想指出我有一个解决方案,但令人费解的是为什么 MSDN 中的示例对我不起作用。我会认为我自己的解决方案并不优雅,所以我仍在寻找更优雅的解决方案。

Exception taskException = null;
var myTask = Task.Run(() =>
    {
        try
        {
            throw new Exception("test");
        }
        catch (Exception e)
        {
            taskException = e;
        }
    });
try
{
    myTask.Wait();
    if (taskException != null) throw taskException;
}
catch (Exception e)
{
    return false;
}

【问题讨论】:

  • 如您所展示的,代码绝对应该到达 catch 块。您使用的是相同的代码还是只是更大代码的演示?
  • @RohitGarg 这是一个大项目的一部分,但出于故障排除的目的,我使用了完全相同的代码(或来自示例),但不知何故它没有到达 catch 块。

标签: c# .net async-await task


【解决方案1】:

当任务运行时,它抛出的任何异常都会被保留并在等待任务结果或任务完成时重新抛出

task.Wait()  Rethrows any exceptions

task.Result  Rethrows any exceptions

同样,您的代码也可以正常工作

在捕获异常时只需按 f5 键,您就会明白这一点

【讨论】:

  • 这是 MSDN 文章所暗示的,但显然它不是为我做的。
【解决方案2】:

根据to MSDNTask.Run:

将指定工作排入队列以在线程池上运行,并返回代表该工作的 Task 对象。

因此,您将异常抛出到与试图捕获它不同的线程上。您应该在同一线程上处理异常。

或者,您可以在全局 AppDomain.UnhandledException 事件中处理未处理的异常。

【讨论】:

    【解决方案3】:

    Jai,如前所述,此代码将始终有效。我认为您必须在 Visual Studio 中启用一些设置。该设置已关闭,因此,您会收到“用户代码未处理的异常”。

    尝试检查工具、选项、调试、常规、仅启用我的代码。

    此外,如果您不想打扰 try/catch 的内容,您可以使用以下内容:

    myTask.ContinueWith(<you can access Exception property here to see if there was an exception>)
    

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题,用 ContinueWith 解决了

      见:

      var task = Task.Run(() =>
                      {
                          ChatHubWrapper chatHub = Ordem_ServicoBLL.sendMensagemIniciarChatPelaVr(pessoaWrapper.OrdemServico);
      
                          foreach (var mensagem in chatHub.MensagensEnviadas)
                              ChatHub.sendMensagemTodaSala(pessoaWrapper.OrdemServico.ID, mensagem);
                      })
                      .ContinueWith((t) =>
                      {
                          if (t.IsFaulted)
                              setPanelErrorWhats(t.Exception.InnerException.Message); // or throw new Exception...
                      });
      
                      task.Wait();
      
                      if (task.IsCompleted)
                          Response.Redirect(pessoaWrapper.OrdemServico.getUrlViewOSSuporte());
      
      

      有了这个你就不需要创建异常 taskException = null;

      而且不好用catch里面Task.Run

      【讨论】:

      • 您还没有指定scheduler 参数,因此继续将在TaskScheduler.Current 上运行。这可能不是你想要的。您可以查看以下链接:12
      • 另外,由于这个问题的问题与Visual Studio调试器有关,而不是与.NET运行时独立运行时的实际可执行文件有关,我认为适当的解决方案将涉及配置调试器,而不是试图“修复”完全正确和有效的代码。
      【解决方案5】:

      @Jai,请尝试将 Task.Run 移动到 try/catch 块的内部。我认为 Task.Run 会立即执行,因此您可能会因此遇到异常。

      【讨论】:

      • 其实我在很多层面都有尝试/捕捉。有一种包围方法的全部内容,一种包围方法的调用者,还有一种包围在示例中。
      • 我们看不到您应用的其余部分,因此只有您在问题中粘贴的这一代码部分。那么你能把这条线移到 try 块吗?我们将消除可能的一个原因。那我们就看看吧。
      猜你喜欢
      • 2017-04-17
      • 2013-08-11
      • 2015-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-29
      • 1970-01-01
      相关资源
      最近更新 更多