【问题标题】:Does HostingEnvironment.QueueBackgroundWorkItem really delay recycling?HostingEnvironment.QueueBackgroundWorkItem 真的会延迟回收吗?
【发布时间】:2023-03-16 09:44:01
【问题描述】:

我读过this documentation,上面写着HostingEnvironment.QueueBackgroundWorkItem 的运行动作:

与普通的 ThreadPool 工作项不同,ASP.NET 可以跟踪通过此 API 注册的工作项当前正在运行的数量,并且 ASP.NET 运行时将尝试延迟 AppDomain 关闭,直到这些工作项完成执行.不能在 ASP.NET 管理的 AppDomain 之外调用此 API。提供的 CancellationToken 将在应用程序关闭时发出信号。

所以我写了这个示例代码:

private void Check() {   
  HostingEnvironment.QueueBackgroundWorkItem(ct => CheckRecyclingBehaviour(ct));}
}

private async void CheckRecyclingBehaviour(CancellationToken ct) {
  while (true) {
    await Task.Delay(1000);
    if (ct.IsCancellationRequested) {
      AppendToFile("Recycling soon...");
      await Task.Delay(1000);
      AppendToFile("But we still have time to finish...");
      break;
    }
  }
}

我已经运行了check()(在 IIS 7 上),过了一会儿我强制通过 IIS 管理器进行回收。

最后,我检查了 debug.txt 文件,其中包含一行:“Recycling Soon...”。

所以我猜 CancellationToken 已发出信号,但 AppDomain 关闭并没有真正延迟(因为第二次打印从未发生过)。

这似乎很奇怪,尤其是考虑到我读过的几篇帖子说recycling will be delayed by 30 seconds

我错过了什么吗?

【问题讨论】:

    标签: c# asp.net iis recycle


    【解决方案1】:

    您正在使用async void,这就是让您感到困惑的原因。正如我在my MSDN article on async best practices, you should avoid async void 中描述的那样。

    async void 更改为正确的async Task,您可能会看到它正常工作。

    更多信息:检测async void 方法的完成并非易事,因此您发布到QueueBackgroundWorkItem 的代码实际上几乎立即完成(在第一个await)。当 ASP.NET 关闭时,它会设置取消令牌(将第一行同步写入文件),然后等待任何排队的工作。由于工作已经完成,它只是立即拆除应用程序域,放弃该方法的其余部分。

    如果您使用async Task 方法,那么QueueBackgroundWorkItem 将理解在任务完成之前代码不完整。

    【讨论】:

    • 实际上我不知道这是否会完全解决它,我可能错了,但我认为强制回收不尊重QueueBackgroundWorkItem中运行的任务,只有当它“自然发生”时它尊重队列吗?将其更改为 Task 将修复它以进行自然回收,但我仍然认为强制回收的行为相同。
    • 谢谢,我改成Task 并且成功了。 Scott,感谢您的警告,但幸运的是,强制回收确实尊重正在运行的任务。
    猜你喜欢
    • 2012-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    • 2014-06-22
    • 1970-01-01
    • 2013-07-22
    • 2019-11-13
    相关资源
    最近更新 更多