[英]asp.net mvc 4 async controller hanging on none TaskAsync methods
[英]Is this the way to change my asp.net mvc controller to call different methods using async?
我嘗試更改現有的asp.net mvc控制器代碼,以便用戶不必等待該代碼執行其他任務(例如db.update行),調用外部API並發送電子郵件確認。 我不確定這個新的異步代碼是否會以不希望的方式阻塞我的線程。
這是我過去的“同步” asp.net控制器方法:
[HttpPost]
public ActionResult CompletePackingItem(int packingId, int orderId, int nextOrderId)
{
List<OrderItem> orders = new List<OrderItem>();
OrderItem order = new BLOrder().GetOrder(orderId);
if (order.HasBeenPaid && order.IsLabelPrinted && (order.Status == (int)BLOrder.OrderStatus.WaitingFor || order.Status == (int)BLOrder.OrderStatus.WorkingOn))
{
new Shoply.Data.Shared.DLWarehousePackingOperation().UpdateIsCompleted(order.OrderId);
string htmledInvoice = new Shoply.Business.Invoice.BLInvoice().GetInvoiceHtmlFormatted(order.OrderId, false);
byte[] pdfByted = BLOrdersPdfExport.SaveOrderAsPdf(htmledInvoice, false);
new UserMailer().SendOrderShippedEmail(order.OrderId, pdfByted);
new Shoply.Data.DLOrders().UpdateOrderToHasBeenSent(order.OrderId);
decimal orderTotalInclDeliveryPrice = order.Total + order.DeliveryPrice;
bool isSuccess = new QuickpayApiService().CapturePayment(order.TransactionId, orderTotalInclDeliveryPrice);
}
return RedirectToAction("index", new { packingId = packingId, orderId = nextOrderId });
}
這是我的新版本:
[HttpPost]
public ActionResult CompletePackingItem(int packingId, int orderId, int nextOrderId)
{
List<OrderItem> orders = new List<OrderItem>();
OrderItem order = new BLOrder().GetOrder(orderId);
if (order.HasBeenPaid && order.IsLabelPrinted && (order.Status == (int)BLOrder.OrderStatus.WaitingFor || order.Status == (int)BLOrder.OrderStatus.WorkingOn))
{
new Shoply.Data.Shared.DLWarehousePackingOperation().UpdateIsCompleted(order.OrderId);
Task.Run(() => AsyncCalling(order));
}
return RedirectToAction("index", new { packingId = packingId, orderId = nextOrderId });
}
private void AsyncCalling(OrderItem order)
{
string htmledInvoice = new Shoply.Business.Invoice.BLInvoice().GetInvoiceHtmlFormatted(order.OrderId, false);
byte[] pdfByted = BLOrdersPdfExport.SaveOrderAsPdf(htmledInvoice, false);
new UserMailer().SendOrderShippedEmail(order.OrderId, pdfByted);
new Shoply.Data.DLOrders().UpdateOrderToHasBeenSent(order.OrderId);
decimal orderTotalInclDeliveryPrice = order.Total + order.DeliveryPrice;
bool isSuccess = new QuickpayApiService().CapturePayment(order.TransactionId, orderTotalInclDeliveryPrice);
}
在新版本中,我正在使用“異步”功能,希望它可以直接跳回到用戶並異步處理任務,並希望不會不必要地阻塞線程。 這是以異步方式調用任務的正確方法,還是當我想要使用fireandforget方式處理任務以使控制器立即返回給用戶時,這是正確的方法嗎?
您需要更改您的方法簽名
private void AsyncCalling(OrderItem order)
至
private Task AsyncCalling(OrderItem order)
您正在告訴編譯器“我正在執行此任務並將控制權交還給您”。 其余代碼對我來說看起來不錯。
是的,如果您以描述的方式使用Task.Run而不在主asp.net線程(即Task.Wait()
)上等待它,則ASP.Net引擎將完成執行主線程而不會被Task.Run和快速返回瀏覽器。 同樣,您將無法讓用戶知道由於Task.Run方法中運行的代碼而導致的結果(它可能引發了異常或成功執行了,用戶將永遠不知道那部分代碼發生了什么)。
但是,當控制權返回給瀏覽器時,asp.net線程池線程仍將被使用,因為Task.Run可能會繼續運行,即使將響應發送回瀏覽器也是如此。 因此,您將快速返回瀏覽器,但是asp.net應用程序無法通過這種方法獲得任何收益。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.