我正在尝试学习如何在MVC2中使用AsyncController,但是几乎没有文档/教程。我正在寻找一个普通的控制器方法,有一个非常慢的输出到第三方服务,并将其转换为异步方法。
原始的控制器方法:
public JsonResult SaveSalesInvoice(SalesInvoice invoice)
{
SaveInvoiceToDatabase(invoice); // this is very quick
ExportTo3rdParty(invoice); // this is very slow and should be async
}所以我创建了一个继承自AsyncController的新控制器:
public class BackgroundController : AsyncController
{
public void ExportAysnc(int id)
{
SalesInvoice invoice = _salesService.GetById(id);
ExportTo3rdParty(invoice);
}
public void ExportCompleted(int id)
{
// I dont care about the return value right now,
// because the ExportTo3rdParty() method
// logs the result to a table
}
public void Hello(int id)
{
}
}然后从jQuery调用Export方法:
function Export() {
$.post("Background/Export", { id: $("#Id").val() }, function (data) {
// nothing to do yet
});
}但结果是404 not found (404未找到)错误(未找到背景/导出)。如果我尝试调用Background/Hello或Background/ExportAysnc,则会找到它们。
我做错了什么?
发布于 2011-02-20 16:59:19
确实有两个用例
让我们从第一个案例开始:
public class BackgroundController : AsyncController
{
public void ExportAysnc(int id)
{
AsyncManager.OutstandingOperations.Increment();
Task.Factory.StartNew(() => DoLengthyOperation(id));
// Remark: if you don't use .NET 4.0 and the TPL
// you could manually start a new thread to do the job
}
public ActionResult ExportCompleted(SomeResult result)
{
return Json(result, JsonRequestBehavior.AllowGet);
}
private void DoLengthyOperation(int id)
{
// TODO: Make sure you handle exceptions here
// and ensure that you always call the AsyncManager.OutstandingOperations.Decrement()
// method at the end
SalesInvoice invoice = _salesService.GetById(id);
AsyncManager.Parameters["result"] = ExportTo3rdParty(invoice);
AsyncManager.OutstandingOperations.Decrement();
}
}现在您可以像这样调用它:
$.getJSON(
'<%= Url.Action("Export", "Background") %>',
{ id: $("#Id").val() },
function (data) {
// do something with the results
}
);现在,因为您已经提到了web服务调用,这意味着当您生成web服务的客户端代理时,您有机会发出异步方法(XXXCompleted和XXXAsync):
public class BackgroundController : AsyncController
{
public void ExportAysnc(int id)
{
AsyncManager.OutstandingOperations.Increment();
// that's the web service client proxy that should
// contain the async versions of the methods
var someService = new SomeService();
someService.ExportTo3rdPartyCompleted += (sender, e) =>
{
// TODO: Make sure you handle exceptions here
// and ensure that you always call the AsyncManager.OutstandingOperations.Decrement()
// method at the end
AsyncManager.Parameters["result"] = e.Value;
AsyncManager.OutstandingOperations.Decrement();
};
var invoice = _salesService.GetById(id);
someService.ExportTo3rdPartyAsync(invoice);
}
public ActionResult ExportCompleted(SomeResult result)
{
return Json(result, JsonRequestBehavior.AllowGet);
}
}这是异步控制器的最佳用途,因为它依赖于I/O完成端口,并且在执行冗长的操作期间不会独占服务器上的任何线程。
第二种情况更简单(实际上不需要异步控制器):
public class BackgroundController : Controller
{
public ActionResult Export(int id)
{
// Fire and forget some lengthy operation
Task.Factory.StartNew(() => DoLengthyOperation(id));
// return immediately
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
}这是一个关于异步控制器的nice article on MSDN。
https://stackoverflow.com/questions/5053942
复制相似问题