ASP.NET MVC2 AsyncController 可以访问 HttpContext.Current 吗?

Posted

技术标签:

【中文标题】ASP.NET MVC2 AsyncController 可以访问 HttpContext.Current 吗?【英文标题】:ASP.NET MVC2 Can AsyncController access HttpContext.Current? 【发布时间】:2011-02-19 23:34:17 【问题描述】:

我正在尝试将此方法 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 呢?

【问题讨论】:

【参考方案1】:

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

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

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

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

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

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

来自 MSDN 文档

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

如果回调完成 同步地,回调将是 在下面的线程上执行 控制 ASP.NET 和操作 将被序列化,所以没有 并发问题。调用 Sync() 来自已经在下面的线程 ASP.NET 的控件未定义 行为。

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

您传递给 Begin 方法可以使用 受控制的线程 ASP.NET。因此,您必须检查 调用 Sync() 之前的这种情况。 如果操作完成 同步(也就是说,如果 CompletedSynchronously 为真),则 回调正在原始文件上执行 线程,你不必打电话 同步()。如果操作完成 异步(也就是说, CompletedSynchronously 为假),则 回调正在线程池上执行 或 I/O 完成端口线程和你 必须调用 Sync()。

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

【讨论】:

我为查找 MSDN 文档提供了 +1。

以上是关于ASP.NET MVC2 AsyncController 可以访问 HttpContext.Current 吗?的主要内容,如果未能解决你的问题,请参考以下文章

Wordpress 类似于 ASP.NET MVC2/3 或 ASP.NET 4.0 中的动态永久链接

ASP.NET MVC2 AsyncController 可以访问 HttpContext.Current 吗?

ASP.NET MVC2 自定义 jQuery 验证:客户端

asp.net mvc2.0重写MvcHandler

带有前缀的控件的 Asp.Net MVC2 客户端验证问题

asp.net C# mvc2中controller的无法获取参数