【问题标题】:Thread pool use in .NET REST service implementation.NET REST 服务实现中的线程池使用
【发布时间】:2011-01-05 19:29:35
【问题描述】:

我正在 .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 时,在请求期间存储变量的正确方法是什么?

谢谢。

【问题讨论】:

  • 对最初问题的更新。它的一个线程调用 Application_BeginRequest,另一个线程运行服务代码并执行 Application_EndRequest。更改 ServiceBehavior 参数没有做任何事情。任何帮助将不胜感激。
  • 听起来你正在使用 asp.net 兼容性的东西,或者尝试。您是否尝试过将您的东西实现为消息调度程序或任何其他 wcf 扩展点(而不是使用 asp.net)?
  • @Simon Svensson 我正在关注微软的教程blogs.msdn.com/b/endpoint/archive/2010/01/06/…。这似乎使用 asp.net 兼容性。如果使用其他方法会有什么不同?有什么好地方可以读一读吗?谢谢!
  • @OP:你有没有解决这个问题?

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


【解决方案1】:

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

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

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

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

干杯

【讨论】:

    【解决方案2】:

    您可能需要查看服务实现中的 [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”,并且每个实例都在自己的线程中运行。

    【讨论】:

    • 谢谢劳伦斯。我已经设置了 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)] 但在 Application_BeginRequest 和 Application_EndRequest 上调用 Thread.CurrentThread.GetHashCode().ToString() 返回不同的值,我做错了什么吗?跨度>
    猜你喜欢
    • 2014-04-12
    • 2012-09-04
    • 2011-07-14
    • 1970-01-01
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    相关资源
    最近更新 更多