简体   繁体   English

多线程或异步,用于网站中的冗长任务

[英]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. 我试图用thread.start创建一个后台线程,但问题是我松开了会话,这是不可理解的。

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? 如果你去Async,会怎么样?

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. 首先,在ASP.NET站点中运行后台线程是一个很大的禁忌,因为您无法控制应用程序的生命周期。 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. 您可以使用数据库来存储任务(并在作业进行时更新其状态),或者只是创建一个执行作业的Windows服务或类似服务。


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). 由于您无法控制正在运行的作业,因此询问您是否应该使用Async或线程是毫无意义的,因为它们都不会释放任何资源(即使您的应用程序运行得更快)。

Simply choose the one that you know and let the HTTP request complete. 只需选择您知道的那个并让HTTP请求完成即可。 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. 另一种方法是使用Ajax或ASP.NET SignalR来检查后台进度。

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") 现在在您的页面上: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 你将不得不设置像Tejs指出的ajax请求,它可以在任务完成时通知用户

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. 在实际启动ajax之前,您可能想在/ MyWebSite上调用SomeClass.Current.IsTaskFinished(ContextBoundObject.Transaction.Id) ..在转换已经完成的情况下。

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. 我会把冗长的操作放在队列中(MSMQ,RabbitMQ等),并让工作进程(最好是Windows服务器)将作业出列并执行那些冗长的操作。

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). 只需在应用程序上有一个SignalR端点,然后通过工作进程上的SignalR .NET客户端连接它。 Once a lengthy operation is done, you can inform the connected clients through the SignalR endpoint. 完成冗长的操作后,您可以通过SignalR端点通知连接的客户端。

No matter what you do, avoid background operations under ASP.NET for any data critical operations IMHO as @jgauffin pointed out. 无论你做什么,都要避免在ASP.NET下进行任何数据关键操作的后台操作,如@jgauffin指出的那样。 Here is why: http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx 原因如下: http//haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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