我有一个使用 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 吗?线程任务是在与重定向不同的 Controller 操作中完成的。
谢谢
大卫
最佳答案
这可能违反了 MVC 无状态原则,但一个非常简单的解决方案是针对 session 存储 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();
});
然后您可以稍后在其他 Controller 中检索该任务并在那里等待
。如果已经完成执行将立即继续,否则将等待执行完成后再继续。
类似这样的事情
public async Task<ActionResult> Index()
{
var payPalTask = Session["PaypalTask"] as Task;
await payPalTask;
return RedirectToAction("CompltedPayment");
}
当然,您可能还需要考虑错误处理等。
更新
我应该提到,上述方法将 session 状态存储在内存中。如果您的应用程序使用多个服务器,您可能想要研究粘性 session 或某种分布式缓存(如 redis),则会出现一些复杂情况。
更新2:
我已经发布了一个演示,使用简单的 Task.Delay
来模拟异步方法 here 。如果您构建此 Web 应用程序,然后导航到/InitiatePp,它将启动请求。然后/PpResult/Result 将给出正在运行的任务的状态,而/PpResult/Wait 将等待任务完成。
关于c# - 如何在数据库值之后等待然后继续,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45091275/