HostingEnvironment.QueueBackgroundWorkItem真的会延迟回收吗?

时间:2016-06-15 21:16:17

标签: c# asp.net iis recycle

我已阅读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文件,它包含了一行:“很快回收......”。

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

这看起来很奇怪,特别是考虑到我读过的几篇帖子都说recycling will be delayed by 30 seconds

我错过了什么吗?

1 个答案:

答案 0 :(得分:5)

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

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

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

如果您使用async Task方法,则QueueBackgroundWorkItem会在任务完成之前了解代码未完成。