我读了很多代码试图使用Task.Run
但没有成功。
我想要实现的目标:
我尝试过但不明白为什么它不起作用:
<小时/> 第一版:
protected void btn_Click(object sender, EventArgs e)
{
// Some actions
// Should insert a record in database --> OK
//Tried this call with and without ConfigureAwait(false)
Task.Run(() => MyClass.doWork()).ConfigureAwait(false);
// Should insert a record in database --> OK
// Some actions not blocked by the previous call
}
public static class MyClass
{
public static void doWork()
{
// Should insert a record in database --> NOT INSERTED
}
}
<小时/> 第二版:
protected void btn_Click(object sender, EventArgs e)
{
// Some actions
// Should insert a record in database --> OK
Bridge.call_doWork();
// Should insert a record in database --> OK
// Some actions not blocked by the previous call
}
public static class Bridge
{
public static async Task call_doWork()
{
//Tried this call with and without ConfigureAwait(false)
await Task.Run(() => MyClass.doWork()).ConfigureAwait(false);
}
}
public static class MyClass
{
public static void doWork()
{
// Should insert a record in database --> NOT INSERTED
}
}
所以我称之为Fire&amp;忘记方法,它应该在数据库中插入一条记录,但是没有插入记录。
拨打Fire&amp; amp;之前和之后的插页忘记方法已经完成。
我不知道如何解决我的问题。
答案 0 :(得分:2)
HttpContext
在主线程以外的线程中不可用,所以你不能依赖它。
但是,当您启动任务时,您可以将HttpContext
中的数据传递给您的方法。例如:
Task.Run(() => MyClass.doWork(HttpContext.Current.Session["somedata"])).ConfigureAwait(false);
答案 1 :(得分:2)
为什么我没有通过HttpContext调用获得EventViewer事件?我在使用HostingEnvironment.QueueBackgroundWorkItem而不是Task.Run时得到了一个。
好的,首先,如果您有QueueBackgroundWorkItem
可用,为什么 曾 使用Task.Run
进行即发即弃工作?
正如我在博客中描述的那样using Task.Run
for fire-and-forget on ASP.NET is a really bad idea! QueueBackgroundWorkItem
是最低可行的解决方案,只有当您接受不可靠时才会这样做。
QueueBackgroundWorkItem
除了Task.Run
之外还为你做了一些事情:它使用ASP.NET运行时注册工作(最小化但不消除工作无法完成的可能性),以及它捕获异常并为您记录它们(这就是您看到事件通知的原因)。
所以,你看到了一个异常事件,因为QBWI正在为你做这件事。使用Task.Run
代码,异常将被捕获并放置在返回的Task
(应该是),然后您的代码完全忽略该任务,从而无声地吞噬异常。
是的!我使用HttpContext来获取Session。但是我无法在不改变大量代码的情况下改变它。
正如其他人所说,HttpContext
仅在请求上下文中有效。因此,当您明确运行后台代码时,它当然没有请求上下文。根据定义,后台代码必须独立于请求。
但我认为你忽略了另外一个非常重要的考虑因素:
public static void doWork()
{
// Should insert a record in database --> NOT INSERTED
}
如果doWork
偶尔执行一次,你确定你的应用程序完全没问题吗?因为那背景任务会发生什么。 ASP.NET旨在响应请求,而不是运行后台任务。
所以,每一次在蓝色的月亮中,应该由doWork
插入的记录不会出现。如果这是不可接受的,那么你就不应该忘掉。