【问题标题】:Ignore an exception in an async method忽略异步方法中的异常
【发布时间】:2021-03-18 23:27:04
【问题描述】:

我正在编写一个需要执行一些异步方法的应用程序 (.Net 5)。首先它创建一个 Job,然后它在 Job 中创建一个 Task,然后等待 Task 完成,最后删除 Job。就上下文而言,这些是 Azure Batch 作业和任务,但我提到它只是为了表明我所说的任务不是 .Net 框架任务,而是一个恰好被命名的普通类。除此之外,这与 Azure Batch 相关这一事实没有任何区别。

我已经编写了这个方法来执行这些步骤:

    private async Task ExecuteTask(string jobName, string taskName, CloudTask task)
    {
      string poolName = ConfigurationManager.AppSettings["PoolName"];
      await taskScheduler.QueueBatchJob(poolName, jobName);
      await taskScheduler.QueueBatchTask(jobName, task);
      taskScheduler.WaitForTaskToComplete(jobName, taskName);
      _ = this.taskScheduler.DeleteJob(jobName); // I am intentionally not awaiting here
    }

调用方法有一个try/catch,额外的代码可能需要一段时间才能执行。 我故意不等待 DeleteJob 方法,因为我不需要这样做才能继续,而且我也不关心它是否失败。它在那里进行清理,但以后可能会有另一个过程来进行适当的清理。

现在,我的问题是,如果该方法实际上存在错误会发生什么?如果父方法没有完成,它会被父 try/catch 捕获吗?我绝对不想这样,如果是这样,我怎么能忽略它?

【问题讨论】:

  • 如果您想知道代码运行时会发生什么,那么运行它并看看会发生什么,而不是在互联网上询问陌生人并希望他们是正确的。一旦你知道会发生什么,如果你需要它以不同的方式表现,而你又不知道如何实现它,那么你可能会遇到一个很好的问题。
  • 简短的回答是视情况而定。如果DeleteJob 同步失败,则调用方法中的try/catch 将捕获异常,如果调用方法等待返回任务。如果DeleteJob本身是异步状态机,则不会抛出异常,但未观察到的异常(如果有)会触发this事件。

标签: c# .net async-await .net-5


【解决方案1】:

我将简单地用here的一些引述来回答这个问题:

Async void 方法具有不同的错误处理语义。当一个 异常是从异步任务或异步任务方法中抛出的,即 异常被捕获并放置在 Task 对象上。使用异步无效 方法,没有 Task 对象,所以任何异常都会抛出 async void 方法将直接在 在异步 void 方法时处于活动状态的 SynchronizationContext 开始了。

稍后在同一篇文章中

当你等待一个Task时,第一个异常被重新抛出,这样你就可以捕捉到特定的异常类型(例如InvalidOperationException)。

这基本上意味着: 该方法返回的Task 将包含Exception,但只有在您await 时才会引发它。因此,不等待Task 会导致所有异常都被Task 对象吞没。

【讨论】:

  • 谢谢。我喜欢这篇文章,但英语是我的第二语言,它技术性太强,无法完全掌握。我理解了 void 部分,但不等待吞下异常的任务让我逃脱了……它仍然如此,我阅读了引号,但我仍然不明白。 [...] 5 次重读后,我想我现在可以理解其中的含义了。
  • 总结:你不会await Task = no Exception 抛出异步方法
猜你喜欢
  • 2022-11-11
  • 2011-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-07
  • 1970-01-01
相关资源
最近更新 更多