3

我阅读了很多试图使用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 方法之前和之后的插入已完成。

我不知道如何解决我的问题。

4

2 回答 2

3

HttpContext将在主线程以外的线程中不可用,因此您不能依赖它。

但是您可以HttpContext在启动任务时将数据传递给您的方法。例如:

Task.Run(() => MyClass.doWork(HttpContext.Current.Session["somedata"])).ConfigureAwait(false);
于 2016-05-03T15:16:03.740 回答
2

为什么我没有通过 HttpContext 调用获得 EventViewer 事件?我在使用 HostingEnvironment.QueueBackgroundWorkItem 而不是 Task.Run 时得到了一个。

好的,首先,如果QueueBackgroundWorkItem有空,你为什么要使用即发即弃的工作?Task.Run

正如我在博客中所描述的,在 ASP.NET 上使用Task.Run即发即弃是一个非常糟糕的主意!QueueBackgroundWorkItem最小可行的解决方案,并且只有在您接受不可靠性的情况下。

QueueBackgroundWorkItem除此之外,它还为您做了几件事Task.Run:它向 ASP.NET 运行时注册工作(这最大限度地减少但不会消除工作无法完成的可能性),它捕获异常并为您记录它们(这就是为什么您正在查看事件通知)。

因此,您看到了您的异常事件,因为 QBWI 正在为您执行此操作。而对于Task.Run代码,异常将被捕获并放置在返回的Task(应该如此)上,然后您的代码完全忽略了该任务,从而默默地吞下了异常。

是的!我使用 HttpContext 来获取会话。但是如果不更改大量代码,我就无法更改它。

正如其他人所指出的,HttpContext仅在请求上下文中有效。因此,当您显式运行后台代码时,它当然没有请求上下文。根据定义,后台代码必须独立于请求。


但是我认为您忽略了另一个非常重要的考虑因素:

public static void doWork()
{
    // Should insert a record in database --> NOT INSERTED
}

doWork如果偶尔不执行,您确定您的应用程序完全正常吗?因为这就是后台任务发生的事情。ASP.NET 旨在响应请求,而不是运行后台任务。

所以,每逢千载难逢,应该插入的记录doWork就不会出现。如果这是不可接受的,那么您不应该进行即发即弃。

于 2016-05-04T17:39:05.557 回答