【问题标题】:Do you have to await async methods?你必须等待异步方法吗?
【发布时间】:2023-04-06 07:35:01
【问题描述】:

假设您有一个服务 API 调用。被调用者在某种程度上对性能至关重要,因此为了不让 API 调用超过必要的时间,使用了 SaveAsync() 方法。但是,我不能 await 它,因为这会使 API 调用与非异步版本一样长(甚至可能更长)。

我要问的原因是:如果你await 调用,返回的Task 对象是否有可能被垃圾回收?如果是这样,那会中断正在运行的任务吗?

【问题讨论】:

  • 你能在哪里等待这个方法吗?
  • 你确定 await 会持有 API 吗?据我所知,等待点将存储在空间块中,当结果出来时,CLR 会处理你的等待部分代码

标签: c# .net asynchronous async-await task-parallel-library


【解决方案1】:

我问的原因是:如果您不等待调用,返回的 Task 对象是否有可能被垃圾收集?

一般来说,不,这不应该发生。将任务排队的底层TaskScheduler 通常会在所需的生命周期内保留对它的引用,直到它完成。你可以在TaskScheduler.QueueTask的文档中看到:

一个典型的实现会将任务存储在一个内部数据结构中,该结构将由在未来某个时间执行这些任务的线程提供服务。

真正的问题在于 ASP.NET SynchronizationContext,它会在运行时跟踪任何正在进行的异步操作。如果您的控制器操作在异步操作之前完成,您将得到一个异常。

如果您想在 ASP.NET 中进行“即发即弃”操作,则应确保通过HostingEnvironment.QueueBackgroundWorkItem BackgroundTaskManager 向 ASP.NET 运行时注册它们

【讨论】:

  • 对我来说幸运的是,它托管在 Windows 服务中,而不是 asp.net 中。但这对于任何想在 asp.net 中执行此操作的人来说都是很好的信息。
【解决方案2】:

不,它不会中断正在运行的任务,但您也不会观察到任务中的异常,这不是很好。您可以(至少部分)通过将所有正在运行的代码包装在 try ... catch 中并记录异常来避免这种情况。

另外,如果您在 asp.net 中,那么您的整个应用程序可能会被停止或回收,在 这种 情况下,您的任务将被中断。这更难避免 - 您可以注册 AppPool 关闭通知,或使用 Hangfire 之类的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    • 2020-03-10
    • 1970-01-01
    相关资源
    最近更新 更多