火与火忘记使用Task.Run工作的方法

时间:2016-05-03 14:41:45

标签: c# asp.net task fire-and-forget

我读了很多代码试图使用Task.Run但没有成功。

我想要实现的目标:

  • 在ASP.NET WebForm事件(单击事件处理程序)中调用Fire&忘记方法(不阻止当前的执行流程)。

我尝试过但不明白为什么它不起作用:

<小时/> 第一版:

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;之前和之后的插页忘记方法已经完成。

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

2 个答案:

答案 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 ideaQueueBackgroundWorkItem最低可行的解决方案,只有当您接受不可靠时才会这样做。

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插入的记录不会出现。如果这是不可接受的,那么你就不应该忘掉。