【问题标题】:asp.net mvc 4.5: getting HostingEnvironment.QueueBackgroundWorkItem to workasp.net mvc 4.5:让 HostingEnvironment.QueueBackgroundWorkItem 工作
【发布时间】:2015-12-22 23:14:51
【问题描述】:

我正在尝试完成一些轻量级任务控制器完成他的工作之后,我为此使用HostingEnvironment.QueueBackgroundWorkItem()

我看到一个奇怪的行为,所以我为此制作了一个人工的概念验证应用程序。

在我的global.asax.cs 我有这个不错的功能:

public class MvcApplication : HttpApplication
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    public static void ContinueWorkOnBackground(Task workItem)
    {
        workItem.ContinueWith(t =>
        {
            if (t.IsFaulted)
            {
                var ex = t.Exception;
                logger.Error(ex);
            }
        });
        HostingEnvironment.QueueBackgroundWorkItem(_ => workItem);
    }

在我的控制器中,我创建了一个工作项并将其扔到那里:

public ActionResult About()
{
    logger.Info("About");
    ViewBag.Message = "Your application description page.";
    MvcApplication.ContinueWorkOnBackground(TestWorkItem());
    return View();
}

private async Task TestWorkItem()
{
    logger.Trace("TestWorkItem");
    await Task.Delay(500);
    logger.Trace("let's fail");
    throw new NotImplementedException();
}

我在日志中看到消息“TestWorkItem”,但从来没有“让我们失败”,也没有错误消息。

我还使用了HostingEnvironment.QueueBackgroundWorkItem((Func<CancellationToken,Task>)(_ => workItem)); 来确保通话没有歧义。

我该如何解决这个问题?

【问题讨论】:

  • NLog 生命周期是否以任何方式与请求相关联?附带说明,当await 可用时,最好不要使用ContinueWith
  • NLog 在那里。我可以打开主页并看到它附加到日志中。

标签: asp.net-mvc asp.net-mvc-4 task-parallel-library


【解决方案1】:

您的问题是TestWorkItem 正在捕获当前请求上下文,并在其await 之后尝试在该请求上下文上恢复。 (我在我的博客上解释了how this capture/resume works)。由于请求已完成,请求上下文在尝试恢复时已不存在。

最好的解决办法是允许QueueBackgroundWorkItem 在请求上下文之外执行代码。因此,首先将您的辅助方法更改为采用Func<Task> 而不是Task

public static void ContinueWorkOnBackground(Func<Task> workItem)
{
  HostingEnvironment.QueueBackgroundWorkItem(async _ =>
  {
    try
    {
      await workItem();
    }
    catch (Exception ex)
    {
      logger.Error(ex);
    }
  });
}

那么你可以这样称呼它:

public ActionResult About()
{
  logger.Info("About");
  ViewBag.Message = "Your application description page.";
  MvcApplication.ContinueWorkOnBackground(() => TestWorkItem());
  return View();
}

【讨论】:

  • 确实如此。在阅读了有关捕获上下文的内容后,我立即理解了这一点(但在我玩代码时未能获得那个小时之前)。谢谢。
猜你喜欢
  • 2013-06-01
  • 2011-04-17
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 2012-12-13
  • 1970-01-01
相关资源
最近更新 更多