ASP.NET MVC3 如何通过跨 Action 调用共享单个 AsyncManager 实例来避免多线程错误?

Posted

技术标签:

【中文标题】ASP.NET MVC3 如何通过跨 Action 调用共享单个 AsyncManager 实例来避免多线程错误?【英文标题】:How does ASP.NET MVC3 avoid multithreading bugs by sharing single instance of AsyncManager across Action invocations? 【发布时间】:2014-09-12 01:58:56 【问题描述】:

我是 asp.net mvc3 的新手。我正在尝试实现一个异步控制器。由于我们代码库的限制,我只能使用 mvc3(不能使用 mvc4)。我看到 mvc3 提供了一个 AsyncManager 类。比方说 线程 0 创建我的控制器的实例和 AsyncManager 的扩展实例。

然后action方法被同时调用:

线程 1: t = 0s

public void ActionAsync()

   this.AsyncManager.Parameters["foo"] = "bar"; 
   // rest of code omitted - suppose it makes a http call to get some data

线程 2: t = 0s

public void ActionAsync()

   this.AsyncManager.Parameters["foo"] = "spam"; // won't foo get overwritten?
   // rest of code omitted - suppose it makes a http call to get some data

现在,当响应第一次调用 ActionAsync 的已完成方法在 1 秒后被调用时:

线程 3: t = 1s

public ActionResult ActionCompleted(string foo)

   // won't foo become corrupted here?


我认为应该在每次调用 Action 方法时创建一个唯一的 AsyncManager 实例并将其关联,但看起来 asp.net mvc3 为每个控制器实例创建一个 AsyncManager 实例。它如何在并发操作调用中使用相同的实例?

另一种情况:线程 1 调用 ActionAsync 并在该方法中进行 http 调用并递增 AsyncManager.OutstandingOperations。同时线程 2 调用 ActionAsync 并进行 http 调用并递增 AsyncManager.OutstandingOperations。 1 秒后,第一次 http 调用完成,AsyncManager.OutstandingOperations 递减 - 但ActionCompleted 方法不会被调用,因为AsyncManager.OutstandingOperations 不会为零。显然我错过了什么

【问题讨论】:

【参考方案1】:

看起来我找到了问题的答案。通过以下链接为每个请求创建一个新的控制器实例:ASP.NET MVC: Is Controller created for every request?ASP.NET MVC Controller Lifecycle

所以每次调用 Action 方法时都会有一个单独的AsyncManager

【讨论】:

以上是关于ASP.NET MVC3 如何通过跨 Action 调用共享单个 AsyncManager 实例来避免多线程错误?的主要内容,如果未能解决你的问题,请参考以下文章

ASP.Net MVC3 通过或不通过 Visual Studio 修改日期和小数的区域性?

asp.net MVC3 中获取发送请求(ajax或ashx)的源地址,即浏览器地址栏上的地址,不是请求的地址

如何在 ASP.NET MVC3 中通过 HTTPS 提供静态文件(在 ~/Content 中)

如何使用 ASP.NET MVC3 编辑嵌套模型

如何在 ASP.net MVC3 中获取 Advantage Database 数据?

如何使用 MVC3 ASP.NET 4.5 和 EF6 基于实体属性注释对 TextBoxFor 进行舍入