0

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");   
} 
jgauffin
  • 99,844
  • 45
  • 235
  • 372
raphadesa
  • 349
  • 1
  • 5
  • 11
  • Are you trying to fix the fact that the user has to wait a long time, or are you trying to make this lengthy process stop hurting your overall scalability as much as it currently does? – Clay Fowler Jul 22 '13 at 19:32
  • Your actual problem is that it sounds like you want the client to update with some UI while the lengthy task is running, yes? If so, then this question is more or less pointless because you need to make an ajax request endpoint to determine the status of your long running task. – Tejs Jul 22 '13 at 19:33
  • Async is actually launching a thread, however you are just freeing up server resources, not really making things faster for the user. – Robert Hoffmann Jul 22 '13 at 19:39
  • 2
    I removed your request for MVP answers as it's a really pointless request. Answers here are upvoted or dowvoted based on their quality and not based upon some shiny title. – jgauffin Jul 22 '13 at 19:43

3 Answers3

3

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 (i.e. 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.

jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • 1
    I agree 100%. If you want your solution to scale pretty nicely then consider a service bus or even simpler a pub/sub mechanism that lets another process (windows service maybe) know there is work to be done in the background. – Raciel R. Jul 22 '13 at 19:45
0

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.

Robert Hoffmann
  • 2,366
  • 19
  • 29
  • 1
    Tasks have the same problem as background threads as they use the thread pool. Read more here: http://stackoverflow.com/questions/16254567/asp-net-long-running-task-thread-is-being-aborted-exception – jgauffin Jul 22 '13 at 19:53
  • Not saying to wait ..i agree with database/queue. But you do have to push it there one way or the other. LenghtyTask() could be the actual task, or just the push to the database depending on how secure he wants to make it. – Robert Hoffmann Jul 22 '13 at 19:56
-1

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

tugberk
  • 57,477
  • 67
  • 243
  • 335