JK.*_*JK. 2 c# jquery asynccontroller asp.net-mvc-2
我正在尝试将此方法转换ExportTo3rdParty()为使用AsyncController:
public JsonResult SaveSalesInvoice(SalesInvoice invoice)
{
SaveInvoiceToDatabase(invoice); // this is very quick
ExportTo3rdParty(invoice); // this is very slow and should be async
}
Run Code Online (Sandbox Code Playgroud)
但是ExportTo3rdParty()方法在多个地方使用HttpContext.Current(太多不能改变 - 原始编码器没有使用足够的依赖注入).例如,它调用GetDefaultCurrency().当通过AsyncController调用ExportTo3rdParty()时,这仍然有用吗?
public Currency GetDefaultCurrency()
{
Currency currency;
string key = string.Format("DefaultCurrency_{0}",
HttpContext.Current.User.Identity.Name);
currency = HttpRuntime.Cache.Get(key) as Currency;
if (currency == null)
{
currency = LookupDefaultCurrency();
HttpRuntime.Cache[key] = currency;
}
}
Run Code Online (Sandbox Code Playgroud)
我知道如果我使用Thread.Start,我无法访问HttpContext.Current.但是AsyncController怎么样?
那么让我问你为什么要使用Async控制器?
你觉得它会更快吗?只是因为它慢的东西并不意味着你需要让它变得异步.实际上,由于线程管理/上下文切换开销,您很可能会发现在运行异步时该方法较慢.
从你所展示的两种方法中我可以理解的东西很少.我猜测ExportTo3Party基本上可以"带外"完成.这是一个外部过程.所以你应该做的是使用MSMQ对作业进行排队(这会立即返回),所以它是非阻塞的.并有一些其他进程/应用程序处理排队的作业.此其他进程可以是在服务器上保持运行的常规控制台应用程序(使用Task Sheduler),它只是在作业到达队列后立即处理.
甚至更简单(如果你没有使用MSMQ),只需执行一个外部应用程序(再次使用控制台应用程序),而不是等待应用程序退出.因此,您可以使用System.Diagnostics.Process启动该进程,而不是WaitForExit.
这两种替代方案都是实现我认为ExportTo3rdParty正在做的事情的正确/更好的方式.看到你没有等待这种方法的响应,就归还它.
如果我还没说服你,那么:
来自MSDN文档
如果异步操作方法调用通过使用BeginMethod/EndMethod模式公开方法的服务,则回调方法(即作为Begin方法的异步回调参数传递的方法)可能在不在的线程上执行ASP.NET的控件.在这种情况下,HttpContext.Current将为null,并且应用程序在访问AsyncManager类的成员(如Parameters)时可能会遇到竞争条件.要确保您可以访问HttpContext.Current实例并避免竞争条件,可以通过从回调方法调用Sync()来恢复HttpContext.Current.
如果回调同步完成,则回调将在受ASP.NET控制的线程上执行,操作将被序列化,因此不存在并发问题.从已经受ASP.NET控制的线程调用Sync()具有未定义的行为.
始终在ASP.NET控制的线程上调用ActionCompleted方法.因此,不要从该方法调用fSync().
可以使用ASP.NET控制下的线程调用传递给Begin方法的回调.因此,您必须在调用Sync()之前检查此情况.如果操作同步完成(即,如果CompletedSynchronously为true),则回调正在原始线程上执行,您不必调用Sync().如果操作异步完成(即,CompletedSynchronously为false),则回调正在线程池或I/O完成端口线程上执行,您必须调用Sync().
http://msdn.microsoft.com/en-us/library/ee728598.aspx