简体   繁体   中英

Fire & Forget method using Task.Run not working

I read a lot of codes trying to use Task.Run without success.

What I want to achive:

  • In an ASP.NET WebForm event (click event handler) call a Fire & Forget method (not block the current flow of execution).

What I tried and don't understant why it's not working:


First Version:

 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 } } 


Second Version:

 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 } } 

So I call the Fire & Forget method, which should insert a record in the database, but there's no record inserted.

The inserts before and after the call to the Fire & Forget method are done.

I don't know how to resolve my issue.

HttpContext will not be available in threads other than the main thread, so you can't depend on it.

But you can pass data from HttpContext to your method when you start the task. For example:

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.

OK, first off, if you have QueueBackgroundWorkItem available, why would you ever use Task.Run for fire-and-forget work?

As I describe on my blog, using Task.Run for fire-and-forget on ASP.NET is a really bad idea ! QueueBackgroundWorkItem is the minimum viable solution, and that's only if you accept unreliability.

QueueBackgroundWorkItem does a couple of things for you beyond Task.Run : it registers the work with the ASP.NET runtime (which minimizes but does not eliminate the possibility that the work will not complete), and it catches exceptions and logs them for you (which is why you were seeing the event notifications).

So, you were seeing an event for your exception because QBWI was doing that for you. Whereas with the Task.Run code, the exception would be caught and placed on the returned Task (as it should be), and then your code completely ignored that task, thus silently swallowing the exception.

Yes! I use HttpContext to get the Session. But I can't change that without changing a lot of code.

As others have noted, HttpContext is only valid within a request context. So, when you explicitly run background code, of course it doesn't have a request context. Background code must be independent of requests, by definition.


But there's one other really important consideration that I think you're overlooking:

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

Are you sure that your app is perfectly OK if doWork once in a while doesn't execute? Because that's what happens to background tasks. ASP.NET was designed to respond to requests, not run background tasks.

So, every once in a blue moon, the record that should have been inserted by doWork won't show up. If this is unacceptable, then you shouldn't be doing fire-and-forget.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM