【发布时间】:2018-09-05 22:21:11
【问题描述】:
如果我运行我的 WCF 服务(托管在 II7 中)并在 contextinstance 上使用 PerSession,一个会话是否与一个线程相同?当客户端没有进行任何调用但在服务上有会话时会发生什么?会话还在线程中吗?
如果我更改为 PerCall,我假设每次调用都会获得一个线程,并且该线程会在调用结束时返回。
我在哪里可以找到这些信息?
【问题讨论】:
如果我运行我的 WCF 服务(托管在 II7 中)并在 contextinstance 上使用 PerSession,一个会话是否与一个线程相同?当客户端没有进行任何调用但在服务上有会话时会发生什么?会话还在线程中吗?
如果我更改为 PerCall,我假设每次调用都会获得一个线程,并且该线程会在调用结束时返回。
我在哪里可以找到这些信息?
【问题讨论】:
相信你能找到答案和很好的解释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
【讨论】:
“如果我运行我的 WCF 服务(托管在 II7 中)并在 contextinstance 上使用 PerSession,一个会话是否与一个线程相同?”
不,请求将由线程池处理。
“当客户端没有进行任何调用但在服务上有会话时会发生什么?会话是否仍在占用线程?”
不,如果没有请求被服务,会话不会占用线程。 WCF“会话”只是数据;状态绑定到会话 ID。它与线程无关。
【讨论】: