会话、实例化和并发

会话是两个终结点之间发送的所有消息的集合。 实例化是指对用户定义的服务对象以及与其相关的 InstanceContext 对象的生存期的控制。 并发 是一个术语,用于控制同时执行的 InstanceContext 线程数。

本主题介绍这些设置、如何使用它们以及它们之间的各种交互。

会议

当服务协定将 ServiceContractAttribute.SessionMode 属性 SessionMode.Required设置为时,该协定表示所有调用(即支持调用的基础消息交换)都必须是同一会话的一部分。 如果协议规定允许会话但不要求会话,客户端可以连接并选择启动或不启动会话。 如果会话结束后再通过同一基于会话的通道发送消息,则会引发异常。

WCF 会话具有以下主要概念性功能:

  • 它们是由调用应用程序显式启动和终止的。

  • 会话期间传递的消息按接收顺序进行处理。

  • 会话将一组消息相互关联,从而形成对话。 该关联的含义是抽象。 例如,一个基于会话的通道可能会基于共享网络连接关联消息,而另一个基于会话的通道可能会基于消息正文中的共享标记关联消息。 可以从会话派生的功能取决于关联的性质。

  • 没有与 WCF 会话关联的常规数据存储。

如果你熟悉 System.Web.SessionState.HttpSessionState ASP.NET 应用程序中的类及其提供的功能,你可能会注意到该会话和 WCF 会话之间的以下差异:

  • ASP.NET 会话始终是服务器发起的。

  • ASP.NET 会话本质上是无序的。

  • ASP.NET 会话提供跨请求的常规数据存储机制。

客户端应用程序和服务应用程序以不同的方式与会话交互。 客户端应用程序启动会话,然后接收并处理会话中发送的消息。 服务应用程序可以使用会话作为扩展点来添加其他行为。 这可以通过直接处理 InstanceContext 或实现自定义实例上下文提供程序来完成。

实例化

实例化行为(使用 ServiceBehaviorAttribute.InstanceContextMode 属性进行设置)控制如何创建 InstanceContext 以响应传入的消息。 默认情况下,每个对象 InstanceContext 都与一个用户定义的服务对象相关联,因此(在默认设置中)设置 InstanceContextMode 属性还控制用户定义的服务对象的实例化。 InstanceContextMode枚举定义实例化模式。

可以使用下列实例化模式:

  • PerCall:为每个客户端请求创建一个新的 InstanceContext (以及相应的服务对象)。

  • PerSession:为每个新的客户端会话创建一个新的 InstanceContext (以及相应的服务对象),并在该会话的生存期内对其进行维护(这需要使用支持会话的绑定)。

  • Single:单个 InstanceContext (因此服务对象)处理应用程序生存期的所有客户端请求。

下面的代码示例演示 InstanceContextMode 的默认值(在服务类上显式设置了 PerSession )。

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class CalculatorService : ICalculatorInstance
{
    ...  
}  

虽然 ServiceBehaviorAttribute.InstanceContextMode 属性控制 InstanceContext 的释放频率,而 OperationBehaviorAttribute.ReleaseInstanceModeServiceBehaviorAttribute.ReleaseServiceInstanceOnTransactionComplete 属性控制服务对象的释放时机。

已知的单一实例服务

单个实例服务对象的一个变体有时很有用:可以自行创建服务对象,并使用该对象创建服务主机。 为此,您还必须将ServiceBehaviorAttribute.InstanceContextMode属性设置为Single,否则在打开服务主机时会引发异常。

使用 ServiceHost(Object, Uri[]) 构造函数创建此类服务。 当您希望提供一个特定的对象实例供单一实例服务使用时,可以使用它作为实现自定义 System.ServiceModel.Dispatcher.IInstanceContextInitializer 的替代方法。 当服务实现类型难以构造时,可以使用此重载(例如,如果未实现无参数公共构造函数)。

请注意,向此构造函数提供对象时,与 Windows Communication Foundation (WCF) 实例行为相关的某些功能的工作方式不同。 例如,提供单例对象实例时,调用 InstanceContext.ReleaseServiceInstance 不起作用。 同样,将忽略任何其他实例发布机制。 ServiceHost始终表现得就像对所有操作将OperationBehaviorAttribute.ReleaseInstanceMode属性设置为ReleaseInstanceMode.None一样。

共享 InstanceContext 对象

通过自己执行关联,您还可以控制将哪个有会话通道或调用与哪个 InstanceContext 对象相关联。

并发

并发是对 InstanceContext 中在任一时刻处于活动状态的线程数量的控制。 此控制是通过将 ServiceBehaviorAttribute.ConcurrencyModeConcurrencyMode 枚举结合使用来实现的。

有以下三种并发模式可用:

  • Single:每个实例上下文最多允许一个线程同时处理消息。 希望使用相同的实例上下文的其他线程必须阻止,直到原始线程退出实例上下文。

  • Multiple:每个服务实例可以同时有多个线程处理消息。 服务实现必须线程安全才能使用此并发模式。

  • Reentrant:每个服务实例一次处理一条消息,但接受重入操作调用。 服务仅在通过 WCF 客户端对象调用时接受这些调用。

注释

理解和开发能够安全地使用多个线程的代码可能比较困难。 在使用 MultipleReentrant 值之前,请确保为这些模式正确设计服务。 有关详细信息,请参阅 ConcurrencyMode

并发的使用与实例化模式有关。 在PerCall实例化中,并发不相关,因为每个消息都是由一个新的InstanceContext处理的,因此在InstanceContext中从来不会有多个线程同时活动。

下面的代码示例演示如何将 ConcurrencyMode 属性设置为 Multiple.

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class CalculatorService : ICalculatorConcurrency
{
    ...  
}  

会话与 InstanceContext 设置交互

会话与 InstanceContext 之间的交互取决于协定中的枚举值 SessionMode 和服务实现中的属性 ServiceBehaviorAttribute.InstanceContextMode 的组合,这些组合控制了通道与特定服务对象之间的关联。

下表显示了在给定服务的 ServiceContractAttribute.SessionMode 属性值和 ServiceBehaviorAttribute.InstanceContextMode 属性值组合的情况下,支持会话或不支持会话的传入通道的结果。

InstanceContextMode 值 Required Allowed NotAllowed
PerCall -会话通道的行为:每个调用都具有一个会话和 InstanceContext
- 无会话通道的行为:将引发异常。
-会话通道的行为:每个调用都具有一个会话和 InstanceContext
- 无会话通道的行为:每个调用都具有一个 InstanceContext
- 会话通道的行为:将引发异常。
- 无会话通道的行为:每个调用都具有一个 InstanceContext
PerSession - 会话通道的行为:每个通道都具有一个会话和 InstanceContext
- 无会话通道的行为:将引发异常。
- 会话通道的行为:每个通道都具有一个会话和 InstanceContext
- 无会话通道的行为:每个调用都具有一个 InstanceContext
- 会话通道的行为:将引发异常。
- 无会话通道的行为:每个调用都具有一个 InstanceContext
单身 - 会话通道的行为:所有调用都具有一个会话和一个 InstanceContext
- 无会话通道的行为:将引发异常。
- 会话通道的行为:所创建的单一实例或用户指定的单一实例都具有一个会话和 InstanceContext
- 无会话通道的行为:所创建的单一实例或用户指定的单一实例都具有一个 InstanceContext
- 会话通道的行为:将引发异常。
- 无会话通道的行为:所创建的每个单一实例或用户指定的单一实例都具有一个 InstanceContext

另请参阅