asp.net mvc的4.5:让HostingEnvironment.QueueBackgroundWorkItem工作 [英] asp.net mvc 4.5: getting HostingEnvironment.QueueBackgroundWorkItem to work
问题描述
我试图完成一些轻量级的任务后的控制器已经完成了他的工作,我用 HostingEnvironment.QueueBackgroundWorkItem()
这一点。
I'm trying to finish some lightweight tasks after a controller has finished his work and I use HostingEnvironment.QueueBackgroundWorkItem()
for this.
我看到一个奇怪的行为,所以我做的人工验证的概念,应用这一点。
I'm seeing a strange behavior, so I make an artificial proof-of-concept app for this.
在我的的global.asax.cs
我有这个漂亮的功能:
in my global.asax.cs
I have this nice function:
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);
}
在我的控制器,我创建了一个工作项目,并抛出有:
And in my controller I create a workitem and throw there:
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,但从来没有让我们失败,并在错误没有消息。
I see the message "TestWorkItem" in logs, but never "let's fail" and no message on error.
我也做了 HostingEnvironment.QueueBackgroundWorkItem((Func键<的CancellationToken,任务>)(_ =>的工作项目));
,以确保通话一点也不含糊。
I also did HostingEnvironment.QueueBackgroundWorkItem((Func<CancellationToken,Task>)(_ => workItem));
to make sure the call is not ambiguous.
我该如何解决这个问题?
How do I fix this?
推荐答案
您的问题是, TestWorkItem
正在捕获当前请求的背景下,并试图恢复该请求上下文其之后的await
。 (我解释此捕获/恢复的工作原理在我的博客) 。由于请求已完成,请求上下文不再受它试图恢复时间存在。
Your problem is that TestWorkItem
is capturing the current request context, and attempting to resume on that request context after its await
. (I explain how this capture/resume works on my blog). Since the request has completed, the request context no longer exists by the time it attempts to resume.
这样做的最好的解决方法是让 QueueBackgroundWorkItem
执行code的请求上下文之外。因此,首先改变你的辅助方法,采取了 Func键&LT;任务&gt;将
代替工作
:
The best fix for this is to allow QueueBackgroundWorkItem
to execute the code outside of a request context. So, first change your helper method to take a Func<Task>
instead of a Task
:
public static void ContinueWorkOnBackground(Func<Task> workItem)
{
HostingEnvironment.QueueBackgroundWorkItem(async _ =>
{
try
{
await workItem();
}
catch (Exception ex)
{
logger.Error(ex);
}
});
}
然后就可以调用它是这样:
Then you can call it as such:
public ActionResult About()
{
logger.Info("About");
ViewBag.Message = "Your application description page.";
MvcApplication.ContinueWorkOnBackground(() => TestWorkItem());
return View();
}
这篇关于asp.net mvc的4.5:让HostingEnvironment.QueueBackgroundWorkItem工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!