2

我正在尝试将此方法转换ExportTo3rdParty()为使用 AsyncController:

public JsonResult SaveSalesInvoice(SalesInvoice invoice)
{
    SaveInvoiceToDatabase(invoice); // this is very quick 
    ExportTo3rdParty(invoice); // this is very slow and should be async
}

但是 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;
    }
} 

我知道如果我使用 Thread.Start 我无法访问 HttpContext.Current。但是 AsyncController 呢?

4

1 回答 1

5

所以让我问你为什么要使用异步控制器?

你认为它会更快吗?仅仅因为它很慢并不意味着你需要让它异步。事实上,由于线程管理/上下文切换开销,您很可能会发现在异步运行时该方法较慢。

从您展示的两种方法中,我几乎无法理解。我猜 ExportTo3Party 基本上可以“带外”完成。那是通过外部过程。因此,您应该做的是使用 MSMQ 对作业进行排队(这会立即返回),因此它是非阻塞的。并让其他一些进程/应用程序处理排队的作业。这个其他进程可以是在服务器上保持运行的常规控制台应用程序(使用任务调度程序),它只是在作业到达队列时立即处理它们。

或者更简单(如果您没有使用过 MSMQ),只需执行一个外部应用程序(再次控制台应用程序),而不是等待应用程序退出。所以你可以使用 System.Diagnostics.Process 来启动进程而不用 WaitForExit。

这两种选择都是正确/更好的方式来实现我认为 ExportTo3rdParty 正在做的事情。看到您没有等待此方法的响应而不是返回它。

如果我还没有说服你,那么:

来自 MSDN 文档

如果异步操作方法调用使用 BeginMethod/EndMethod 模式公开方法的服务,则回调方法(即作为异步回调参数传递给 Begin 方法的方法)可能会在不在其下的线程上执行ASP.NET 的控制。在这种情况下,HttpContext.Current 将为 null,并且应用程序在访问 AsyncManager 类的成员(例如参数)时可能会遇到竞争条件。为了确保您可以访问 HttpContext.Current 实例并避免竞争条件,您可以通过从回调方法调用 Sync() 来恢复 HttpContext.Current。

如果回调同步完成,回调将在受 ASP.NET 控制的线程上执行,并且操作将被序列化,因此不存在并发问题。从已经受 ASP.NET 控制的线程调用 Sync() 具有未定义的行为。

ActionCompleted 方法将始终在受 ASP.NET 控制的线程上调用。因此,不要从该方法调用 fSync()。

传递给 Begin 方法的回调可能会使用受 ASP.NET 控制的线程来调用。因此,您必须在调用 Sync() 之前检查这种情况。如果操作同步完成(即,如果 CompletedSynchronously 为 true),则回调在原始线程上执行,您不必调用 Sync()。如果操作异步完成(即 CompletedSynchronously 为 false),则回调正在线程池或 I/O 完成端口线程上执行,您必须调用 Sync()。

http://msdn.microsoft.com/en-us/library/ee728598.aspx

于 2011-02-20T06:49:55.913 回答