【问题标题】:WCF 1 Session = 1 Thread?WCF 1 会话 = 1 线程?
【发布时间】:2018-09-05 22:21:11
【问题描述】:

如果我运行我的 WCF 服务(托管在 II7 中)并在 contextinstance 上使用 PerSession,一个会话是否与一个线程相同?当客户端没有进行任何调用但在服务上有会话时会发生什么?会话还在线程中吗?

如果我更改为 PerCall,我假设每次调用都会获得一个线程,并且该线程会在调用结束时返回。

我在哪里可以找到这些信息?

【问题讨论】:

    标签: .net wcf session


    【解决方案1】:

    相信你能找到答案和很好的解释here

    乍一看,出于可扩展性原因,您会使用 PerCall,而对于通常的 Web 场景,您会使用 PerSession

    • 当使用 PerSession 时,一旦客户端第一次调用服务实现的实例将保留在服务器上。每个客户端都有自己的会话,每个客户端仅在一个线程(!) 上执行。 所以,是的,默认情况下是 1 个会话 == 1 个线程。但是您也可以更改 ConcurrencyMode,这样客户端就可以在一个会话中进行多个并发调用。

    • 如果是 PerCall,服务实例将在调用完成后立即释放。

    [已编辑(与 David Nelson 讨论后)]:

    (!) 不代表同一个线程!这只意味着 ThreadPool 将使用可用线程来运行服务代码。但是如果启动1000个并发客户端,ThreadPool会分配很多线程,这涉及到资源,比如内存。

    用代码解释线程使用情况:

    我创建了简单的计算器服务来展示 WCF 服务的踩踏工作原理。

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    public class CalculatorService : ICalculatorService
    {
        private int _threadIdOnCreating = Thread.CurrentThread.ManagedThreadId;
        public int AccumulatedValue { get; private set; }
        public int Accumulate(int valueToAdd)
        {
            AccumulatedValue += valueToAdd;
    
            Console.WriteLine(
    string.Format("Accumulated: {0}. ThreadIdOnServiceCreating:{1} CurrentThreadId:{2}",
                AccumulatedValue, _threadIdOnCreating, Thread.CurrentThread.ManagedThreadId));
    
            return AccumulatedValue;
        }
    }
    

    我使用参数 2 运行 Accumulate 方法五次,然后创建新的客户端代理并执行相同操作。 下面是输出,证明服务器保留了服务实现的实例(创建时的threadId),但是方法在不同的线程上运行,取自ThreadPool。

    I'm calculator
    Accumulated: 2. ThreadIdOnServiceCreating:6 CurrentThreadId:6
    Accumulated: 4. ThreadIdOnServiceCreating:6 CurrentThreadId:7
    Accumulated: 6. ThreadIdOnServiceCreating:6 CurrentThreadId:6
    Accumulated: 8. ThreadIdOnServiceCreating:6 CurrentThreadId:7
    Accumulated: 10. ThreadIdOnServiceCreating:6 CurrentThreadId:6
    Accumulated: 2. ThreadIdOnServiceCreating:9 CurrentThreadId:9
    Accumulated: 4. ThreadIdOnServiceCreating:9 CurrentThreadId:6
    Accumulated: 6. ThreadIdOnServiceCreating:9 CurrentThreadId:9
    Accumulated: 8. ThreadIdOnServiceCreating:9 CurrentThreadId:6
    Accumulated: 10. ThreadIdOnServiceCreating:9 CurrentThreadId:8
    

    【讨论】:

    • 您引用的文档没有说明每个会话在每个客户端的一个线程上执行。你是怎么得出这个结论的?
    • 那篇文章措辞不当,最终不准确。同一会话上的后续请求可以在不同的线程上执行。构建服务来证明这一点非常容易。
    • 谢谢!但是说一个会话打开了但现在没有请求完成,这是否仍然意味着这个会话分配了一个线程,还是会在下一个请求时首先分配线程(如 PerCall)?
    • 正如我在回答中所说,使用会话不会影响 WCF 的线程行为。每个请求都在线程池中的一个线程上处理;如果未处理请求,则 WCF 不会“分配”任何线程(当然它们可以在线程池中保持活动状态)。
    【解决方案2】:

    “如果我运行我的 WCF 服务(托管在 II7 中)并在 contextinstance 上使用 PerSession,一个会话是否与一个线程相同?”

    不,请求将由线程池处理。

    “当客户端没有进行任何调用但在服务上有会话时会发生什么?会话是否仍在占用线程?”

    不,如果没有请求被服务,会话不会占用线程。 WCF“会话”只是数据;状态绑定到会话 ID。它与线程无关。

    【讨论】:

    • 当你说请求由线程池处理不就和使用线程一样吗,即使是线程池分配的?
    • 不,不一样。特别是,不能保证同一会话上的后续请求将使用先前请求使用的同一线程;当一个线程池线程可用时,新请求将由线程池线程提供服务。
    • 嗨...所以我实际上并没有相信你的话,而是建立了带有会话来验证的服务。你是对的,另一个线程可以被一个客户端用于同一个会话。但无论如何,这只意味着有效地使用了 ThreadPool。但是如果启动 1000 个并发客户端 ThreadPool 会分配很多线程,这涉及到资源
    猜你喜欢
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2017-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多