简体   繁体   中英

Multi-Thread or Async for a lengthy task in a website

I am currently running an e-commerce website.

So when the user checkouts, I have a bank callback page...

But as I have to perform a lengthy task after the payment occurs (which is currently done synchronously), the user has to wait a long time before it is redirected back to my site.

I have tried to make a background thread with thread.start but the problem with that is that I loose the session, which is not appreciable.

So, based on this description, how would you proceed? Would you go Async or Multi-Threading?

If you'd go Async, how would it be?

So we have something like:

public ActionResult CallBack()
{
    if (AcceptPayment() == "OK")
    {
      LenghtyTask(); 
    }

    return RedirectToUrl("MyWebSite");   
} 

First of all, running background threads in an ASP.NET site is a big no-no since you have no control over the application lifetime. Application pools can be shut down or recycled, meaning that you loose data.

You can either use a database to store the tasks (and update their state as the job progresses) or simply create a windows service or similar which executes the jobs.


As you have no control over the job running, it's pointless to ask if you should use Async or threading as neither of them will release any resources (ie making your application run faster).

Simply choose the one that you know and let the HTTP request complete. Tell the user that the job is being processed in the background and let him refresh the browser to see how it progresses. An alternative is to use Ajax or ASP.NET SignalR to check the progress in the background.

Would probably go something like this

public ActionResult CallBack()
{
    if (AcceptPayment() == "OK")
    {
        // simply launches the task and moves on
        Task.Run(LenghtyTask()); 
    }

    return RedirectToUrl("MyWebSite");   
} 

Now on you page: RedirectToUrl("MyWebSite")

You are gonna have to setup a ajax request like Tejs pointed out, that can inform the user when the task is finished

public ActionResult IsTaskFinished()
{
    // No clue where your transaction is, but your gonna need to know it to check it's state
    return JSON(SomeClass.Current.IsTaskFinished(ContextBoundObject.Transaction.Id));
} 

Your probably gonna wanna call SomeClass.Current.IsTaskFinished(ContextBoundObject.Transaction.Id) on /MyWebSite before actually launching the ajax ..in case the transation is already finished.

function isTaskFinished() {
    $.post("/IsTaskFinished").always(function(data) {
        if (!!data) {
            setTimout(isTaskFinished, 3000);
        }
        else {
            // yay i'm done, inform user !
        }
    });
}

Of course you have to factor in retry limits, error handling, etc.

I would stuck the lengthy operation in a queue (MSMQ, RabbitMQ, etc.) and have worker process(es) (preferably a windows server) to dequeue the jobs and perform those lengthy operations.

In terms of how you inform the user, there are couple of options but my choice would be real-time updates which you can push through your server to your client browsers. Simply have a SignalR endpoint on your application and connect it through the SignalR .NET client on your worker process(es). Once a lengthy operation is done, you can inform the connected clients through the SignalR endpoint.

No matter what you do, avoid background operations under ASP.NET for any data critical operations IMHO as @jgauffin pointed out. Here is why: http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx

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