.NET REST服务实现中使用线程池

时间:2011-01-05 19:29:35

标签: c# asp.net web-services rest

我正在.NET 4中实现我的第一个REST服务,遇到了意想不到的事情。似乎我不理解微软ServiceModel的强调工作,但却找不到传统方式的答案。

要实现我的网络服务,我遵循了本教程中的步骤:http://blogs.msdn.com/b/endpoint/archive/2010/01/06/introducing-wcf-webhttp-services-in-net-4.aspx

服务有效。让我感到惊讶的是,Global.asax中的Application_BeginRequest和Application_EndRequest由不同的线程调用。查看堆栈跟踪,看起来这些线程基于某种线程池。

如果不进行一些重构,这对我们来说是一个问题,因为我们总是假设单个请求总是在同一个线程上运行,因此我们将一些变量保存在线程本地存储中。变量在Application_BeginRequest中初始化,并在Application_EndRequest中释放。看来,使用ServiceModel这不是正确的方法。

我的问题是:

  1. 在使用ServiceModel时,是否可以假设哪些线程正在运行我的代码?
  2. 有没有办法将执行限制在一个线程?这有什么不好的原因吗?
  3. 使用ServiceModel时,在请求期间存储变量的正确方法是什么?
  4. 谢谢。

2 个答案:

答案 0 :(得分:2)

我建议的一件事是考虑使用WCF挂钩而不是Application_BeginRequest和Application_EndRequest方法。四个实例,这里有四个更有用的钩子:

AfterReceiveRequest - > BeforeCall - >方法调用 - > AfterCall - > BeforeSendReply

钩子非常强大。在调用方法之前检查参数(将一些日志记录集中到一个地方)并执行各种其他有用的操作。这些不是唯一可用的钩子,我也使用其他一些钩子。例如,GetInstance允许我覆盖服务类对象的创建(因此您可以使用依赖注入框架等)。

当我使用每次调用并发模式时,这些钩子加上方法调用本身在同一个线程上调用。希望这可以帮助。如果你愿意,我可以提供实现这些钩子的链接。

干杯

答案 1 :(得分:0)

您可能希望查看服务实现上的[ServiceBehavior]属性,因为它支持参数来控制创建的实例数以及使用的线程模型。

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

当你有

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
                 ConcurrencyMode = ConcurrencyMode.Multiple)] 
public class MyService : IMyService

您的服务将作为单例运行,但具有多个线程 - 最多为WCF配置中设置的阈值 - 调用您的方法。要强制它仅在一个线程上运行,从而序列化入站请求,请设置ConcurrencyMode.Single。

或者,您可以为每次通话启动新服务实例:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
                 ConcurrencyMode = ConcurrencyMode.Single)] 
public class MyService : IMyService

实例只有一个线程可以访问它。实际上,当你有InstanceContextMode.PerCall时,会忽略ConcurrencyMode,因为它始终是“Single”,并且每个实例都在自己的线程中运行。

相关问题