使用 Task.Run 的即发即弃方法无效
Fire & Forget method using Task.Run not working
我阅读了很多尝试使用 Task.Run
的代码,但都没有成功。
我想达到的目标:
- 在 ASP.NET WebForm 事件(单击事件处理程序)中调用 Fire & Forget 方法(不阻止当前的执行流程)。
我试过但不明白为什么它不起作用:
第一版:
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 & Forget 方法,它应该在数据库中插入一条记录,但是没有插入记录。
调用 Fire & Forget 方法前后的插入已完成。
我不知道如何解决我的问题。
HttpContext
在主线程以外的线程中将不可用,因此您不能依赖它。
但是您可以在启动任务时将数据从 HttpContext
传递到您的方法。例如:
Task.Run(() => MyClass.doWork(HttpContext.Current.Session["somedata"])).ConfigureAwait(false);
Why didn't I get an EventViewer event with the HttpContext call? I got one when using HostingEnvironment.QueueBackgroundWorkItem instead of 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
上(应该如此),然后您的代码完全忽略了该任务,从而默默地吞下了异常。
Yes! I use HttpContext to get the Session. But I can't change that without changing a lot of code.
正如其他人所指出的,HttpContext
仅在请求上下文中有效。所以,当你显式 运行 后台代码时,它当然没有请求上下文。根据定义,后台代码必须独立于请求。
但是我认为您忽略了另一个非常重要的注意事项:
public static void doWork()
{
// Should insert a record in database --> NOT INSERTED
}
如果 doWork
偶尔不执行,您确定您的应用程序完全正常吗?因为后台任务就是这样。 ASP.NET 旨在响应请求,而不是 运行 后台任务。
所以,千载难逢,doWork
应该插入的记录不会出现。如果这是不可接受的,那么您不应该进行即发即弃。
我阅读了很多尝试使用 Task.Run
的代码,但都没有成功。
我想达到的目标:
- 在 ASP.NET WebForm 事件(单击事件处理程序)中调用 Fire & Forget 方法(不阻止当前的执行流程)。
我试过但不明白为什么它不起作用:
第一版:
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 & Forget 方法,它应该在数据库中插入一条记录,但是没有插入记录。
调用 Fire & Forget 方法前后的插入已完成。
我不知道如何解决我的问题。
HttpContext
在主线程以外的线程中将不可用,因此您不能依赖它。
但是您可以在启动任务时将数据从 HttpContext
传递到您的方法。例如:
Task.Run(() => MyClass.doWork(HttpContext.Current.Session["somedata"])).ConfigureAwait(false);
Why didn't I get an EventViewer event with the HttpContext call? I got one when using HostingEnvironment.QueueBackgroundWorkItem instead of 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
上(应该如此),然后您的代码完全忽略了该任务,从而默默地吞下了异常。
Yes! I use HttpContext to get the Session. But I can't change that without changing a lot of code.
正如其他人所指出的,HttpContext
仅在请求上下文中有效。所以,当你显式 运行 后台代码时,它当然没有请求上下文。根据定义,后台代码必须独立于请求。
但是我认为您忽略了另一个非常重要的注意事项:
public static void doWork()
{
// Should insert a record in database --> NOT INSERTED
}
如果 doWork
偶尔不执行,您确定您的应用程序完全正常吗?因为后台任务就是这样。 ASP.NET 旨在响应请求,而不是 运行 后台任务。
所以,千载难逢,doWork
应该插入的记录不会出现。如果这是不可接受的,那么您不应该进行即发即弃。