如何在数据库值之后等待然后继续

时间:2017-07-13 21:34:50

标签: c# asp.net-mvc multithreading paypal

我有一个使用PayPal自适应付款的电子商务网站。自适应支付请求从PayPal生成PayKey以创建发票。获得PayKey的延迟时间足够长所以我有想法将代码放在一个单独的线程中,而用户在重定向到PayPal之前回答其他一些问题,请参阅下面的代码:

    await Task.Run<Task>(async () =>
    {
        var payResponse = await _payPalApplicationService.ProceedWithPayPal(currentEvent.Id, order.InvoiceId, order.TrackingId, owners.Single(), vModel.TotalPrice, vModel.DeliveryPriceTotal, orderToAdd.TotalTaxes, orderToAdd.SalesRate + orderToAdd.SalesRateTaxes, vModel.SKUViewModels, _payPalApplicationService.PayPalCore._serviceEndPointUrl);
        order.PayKey = payResponse.payKey;

        _orderService.Update(order);
        await _unitOfWorkAsync.SaveChangesAsync();
    });

我遇到的问题是一些用户可以快速访问,因此在重定向到PayPal之前尚未生成PayKey。

在将用户重定向到PayPal之前,您是否知道我可以做些什么来确保我获得PayKey?线程任务在与具有重定向的控制器动作不同的控制器动作中完成。

谢谢

大卫

1 个答案:

答案 0 :(得分:2)

它可能违反MVC无国籍原则,但一个非常简单的解决方案是将PayKey检索任务存储在会话中。

所以将上面的代码更改为:

Session["PaypalTask"] = await Task.Run<Task>(async () =>
{
    var payResponse = await _payPalApplicationService.ProceedWithPayPal(currentEvent.Id, order.InvoiceId, order.TrackingId, owners.Single(), vModel.TotalPrice, vModel.DeliveryPriceTotal, orderToAdd.TotalTaxes, orderToAdd.SalesRate + orderToAdd.SalesRateTaxes, vModel.SKUViewModels, _payPalApplicationService.PayPalCore._serviceEndPointUrl);
    order.PayKey = payResponse.payKey;

    _orderService.Update(order);
    await _unitOfWorkAsync.SaveChangesAsync();
});

然后,您可以稍后在其他控制器中检索该任务,并在那里await检索该任务。如果它已经完成exectution将立即继续,否则它将等待它继续完成。

像这样的东西

public async Task<ActionResult> Index()
{
    var payPalTask = Session["PaypalTask"] as Task;

    await payPalTask;

    return RedirectToAction("CompltedPayment");
}

当然,您可能还需要考虑错误处理等。

更新

我应该提一下,上面的方法将会话状态存储在内存中。如果您的应用程序使用多个服务器,您可能希望研究粘性会话或某种分布式缓存(如redis),则会出现一些复杂情况。

UPDATE2:

我发布了一个使用简单Task.Delayhere模拟异步方法的演示。如果您构建此Web应用程序,然后导航到/ InitiatePp它将启动请求。然后/ PpResult / Result将给出正在运行的任务的状态,并且/ PpResult / Wait将等待任务完成。