一、服务实例的生命周期概览

我们已经直到,通过显式调用Close方法或等待默认的超时时间到来,都可以释放服务实例。但是,在会话连接里,经常需要按一定顺序调用方法。

二、分步操作

会话契约的操作有时隐含了操作调用的顺序。WCF提供了一种被称之为分步操作(Demarcating Operation)的方法,以应对服务契约的操作需要指定执行顺序的情况。分步操作是使用OperationContract特性的IsInitiating和IsTerminating属性:

[AttributeUsage(AttributeTargets.Method)]
public sealed class OperationContractAttribute : Attribute
{
public bool IsInitiating
{get;set;}
public bool IsTerminating
{get;set;}
//More members
}

IsInitiating属性的默认值为true,IsTerminating属性的默认的属性值则为false,对这些属性设置值会影响生成的WSDL文档。所以以下两个定义是等效的:

 [ServiceContract]
public interface IService5
{
[OperationContract]
void MyMethod();
[OperationContract(IsInitiating=true,IsTerminating=false)]
void MyMethod();
}

默认情况下,操作不能划分会话的执行顺序。调用操作的顺序可以是最先、最后,也可以在会话中其它操作之间。使用属性的非默认值可以指定一个方法不被最先调用,或被最后调用,或者同时符合两个约束条件。

[ServiceContract(SessionMode = SessionMode.Required)]
interface IOrderManager
{
[OperationContract]
void SetCustomerId(int customerId); [OperationContract(IsInitiating = false)]

void AddItem(int itemId); [OperationContract(IsInitiating = false)]

decimal GetTotal( ); [OperationContract(IsInitiating = false,IsTerminating = true)]

bool ProcessOrders( );

}

        此时,操作AddItem()、GetTotal()以及ProcessOrder()都不能是启动会话的第一个操作。同时,ProcessOrder()操作则会成为终止会话的操作。这与业务的要求是一脉相承的。

如果IsInitiating值为true(默认值),并不必然代表该操作必然是启动会话的第一个操作。如果其它相同设置的操作首先被调用,就会启动一个会话,而该操作则在被调用时才加入会话,成为会话的一部分;如果IsInitiating值为false,那就意味着在新的会话中该操作绝对不能作为第一个操作被客户端调用,同时,该方法只能在被调用时才加入会话,成为会话的一部分。

如果IsTermination的值为true,则代表该操作必须是终止会话的操作,然后以异步的方式释放服务实例。此时,客户端不能通过代理发出另外的调用。注意,客户端仍然应该关闭代理。虽然在服务契约定义时,允许将多个操作的IsTerminating值设置为true,但一旦调用了IsTerminating值为true的方法,就不能再调用服务实例的其它方法,除非在客户端重新创建一个代理对象。

三、实例停止

实例停用只针对会话服务而言。单例服务虽然也可以应用,但却无效。

迄今为止描述的会话服务的实例管理技术能够将一个客户端(多个客户端)连接到服务实例上。然而,真正的情形却复杂得多。先前提到过,每个服务实例都被托管在上下文中,如下图所示:

会话实际要做的不仅是关联客户端消息,同时还要关联托管了服务的上下文。启动宿主会创建一个新的上下文。会话终止时,上下文也随之终止。默认情况下,上下文的生命周期与发布的服务实例的生命周期相同。然而,出于优化和可扩展性的目的,WCF设计者提供了一种分离两种生命周期的选项,该选项允许WCF独立地停止实例,而不必依赖于它的上下文。实际上,WCF还允许不包含实例的上下文存在,如上图所示,我们将这种管理技术称为上下文停止。控制上下文停止的最常见办法是通过设置OperationBehavior特性的ReleaseInstanceMode属性。

public enum ReleaseInstanceMode
{
None,
BeforeCall,
AfterCall,
BeforeAndAfterCall,
}
[AttributeUsage(AttributeTargets.Method)]
public sealed class OperationBehaviorAttribute : Attribute,...
{
public ReleaseInstanceMode ReleaseInstanceMode
{get;set;}
//More members
}

ReleaseInstanceMode属性属于ReleaseInstanceMode枚举类型,其值代表了释放与方法相关的实例的时间:调用前,调用后、调用前与调用后,以及调用中。释放实例时,如果服务支持IDisposable接口,则还要停止Dispose()方法,并且Dispose()方法会拥有一个操作上下文。

通常,只需要将实例停止应用到部分(而不是全部)服务方法上,或者为不同的方法设置不同的值。

class MyService : IMyContract,IDisposable
{
[OperationBehavior(ReleaseInstanceMode = ReleaseInstanceMode.AfterCall)]
public void MyMethod( )
{...}
public void MyOtherMethod( )
{...}
public void Dispose( )
{...}
}

配置为ReleaseInstanceMode.None

ReleaseInstanceMode属性的默认值为ReleaseInstanceMode.None。

ReleaseInstanceMode.None意味着实例的生命周期不收调用的影响,如下图所示:

配置为ReleaseInstanceMode.BeforeCall

当方法被配置为配置为ReleaseInstanceMode.None时,如果会话已经存在一个实例,那么在转发调用之前WCF会停止实例,创建一个新的实例取代它,并让这个新的实例维护所要转发的调用,如下图所示:

ReleaseInstanceMode.BeforeCall可以用于优化诸如Create()这样的方法,用这些方法能够获取一些有价值的资源,并且释放原先分配的支援。启动会话时不需要获取资源,而应该等待,直到调用Create()方法,然后释放原先分配的资源,同时获取新的资源。在调用Create方法之后,就应该i准备启动对实例上的其它被配置成ReleaseInstanceMode.None方法的调用。

配置为ReleaseInstanceMode.AfterCall

当方法被配置为配置为ReleaseInstanceMode.AfterCall时,WCF会在调用方法之后停止实例,如下图所示:

这样设计可以优化诸如Cleanup()这样的方法,该方法能够清除实例所持有的有价值的资源,而不需要等到会话结束。通常都会在配置为ReleaseInstanceMode.None方法之后应用ReleaseInstanceMode.AfterCall的方法。

配置为ReleaseInstanceMode.BeforeAndAfterCall

当方法配置为ReleaseInstanceMode.BeforeAndAfterCall时,它结合了ReleaseInstanceMode.BeforeCall和ReleaseInstanceMode.AfterCall的功能。在执行调用之前,如果上下文包含一个实例,那么WCF就会调用前停止实例,再创建一个新的实例去维护调用,然后在调用后停止这个新创建的实例,如下图所示:

显式停止

除了可以通过应用OperationBehaviorAttribute应用ReleaseInstanceMode,也可以通过编程方式在服务的操作中显式地完成对实例的停止。方法是利用InstanceContext的ReleaseServiceInstance()方法:

class MyService : IMyContract,IDisposable
{
public void MyMethod( )
{
//Do some work then
OperationContext.Current.InstanceContext.ReleaseServiceInstance( );
}
public void Dispose( )
{...}
}

这两种实现实例停止的方式还可以结合使用,例如在应用了OperationBehavior特性,并将ReleaseInstanceMode设置为 BeforeCall的方法中,如果显式调用ReleaseServiceInstance()方法,其效果就相当于将 ReleaseInstanceMode设置为BeforeAndAfterCall。

实例停止同样能够影响到单例服务。虽然服务允许这样的定义,但试图停止单例对象的方式是不可取的。

使用实例停止

实例停止是一种优化技术,通常情况下应该尽量避免使用它。只有在无法同时满足系统的性能要求和可伸缩性要求时,才考虑使用实例停止。

[WCF编程]8.服务实例的生命周期的更多相关文章

  1. [ASP.NET Core 3框架揭秘] 依赖注入[8]:服务实例的生命周期

    生命周期决定了IServiceProvider对象采用怎样的方式提供和释放服务实例.虽然不同版本的依赖注入框架针对服务实例的生命周期管理采用了不同的实现,但总的来说原理还是类似的.在我们提供的依赖注入 ...

  2. 前端MVC Vue2学习总结(二)——Vue的实例、生命周期与Vue脚手架(vue-cli)

    一.Vue的实例 1.1.创建一个 Vue 的实例 每个 Vue 应用都是通过 Vue 函数创建一个新的 Vue 实例开始的: var vm = new Vue({ // 选项 }) 虽然没有完全遵循 ...

  3. Vue.js 1.x 和 2.x 实例的生命周期

    在Vue.js中,在实例化Vue之前,它们都是以HTML的文本形式存在文本编辑器中.当实例化后将经历创建.编译.销毁三个主要阶段. 以下是Vue.js 1.x  实例的生命周期图示: Vue.js 1 ...

  4. Vue.js-07:第七章 - Vue 实例的生命周期

    一.前言  在之前的 Vue 学习中,我们在使用 Vue 时,都会创建一个 Vue 的实例,而每个 Vue 实例在被创建时都要经过一系列的初始化过程.例如,需要设置数据监听.编译模板.将实例挂载到 D ...

  5. Vue2.5笔记:Vue的实例与生命周期

    理解与认识 Vue 的实例是我们学习 Vue 非常重要的一步,也是非常必须的,因为实例是它的一个起点,也是它的一个入口,只有我们创建一个 Vue 实例之后,我们才行利用它进行一些列的操作. 首先 Vu ...

  6. vue实例的生命周期

    Vue实例的生命周期也就是这个实例从出生到死亡的过程,所以我在文档原图上把这个周期大致分为创建过程 | 运行过程 | 销毁过程三个阶段,不同结果或又分为一些小的阶段 在第一个阶段,创建阶段,会完成Vu ...

  7. 浅析vue实例的生命周期(生命周期钩子)

    “每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听.编译模板.将实例挂载到 DOM 并在数据变化时更新 DOM 等” ,在不同的生命周期内会经历不同的钩子函数(生命周期 ...

  8. 从零开始学 Web 之 Vue.js(三)Vue实例的生命周期

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

  9. python 全栈开发,Day91(Vue实例的生命周期,组件间通信之中央事件总线bus,Vue Router,vue-cli 工具)

    昨日内容回顾 0. 组件注意事项!!! data属性必须是一个函数! 1. 注册全局组件 Vue.component('组件名',{ template: `` }) var app = new Vue ...

随机推荐

  1. Python黑帽编程1.3 Python运行时与包管理工具

    Python黑帽编程1.3  Python运行时与包管理工具 0.1  本系列教程说明 本系列教程,采用的大纲母本为<Understanding Network Hacks Attack and ...

  2. Functional Programming without Lambda - Part 2 Lifting, Functor, Monad

    Lifting Now, let's review map from another perspective. map :: (T -> R) -> [T] -> [R] accep ...

  3. EF连接PostgreSql

    1.用nuget安装npgsql和EF 注意,Nuget一定要安装Npgsql的2.2.7版本,更高版本nuget在后面安装EF的时候无法自动解析. install-Package Npgsql -V ...

  4. 海淘手表Invicta8926OB到手~晒图

    3月3号通过国内代购网站Hai360海外购下单: 3月5号美亚发货: 3月6号到达转运仓: 3月12号到达天津清关: 清关等了7天: 3月19号转国内快递,我将原武汉地址,改上海,耽误了3天: 3月2 ...

  5. jsp登入oracle

    <body> <% Class.forName("oracle.jdbc.driver.OracleDriver"); Connection conn=null; ...

  6. Nokia 920板砖自救(理论上通用,升级Win10成板砖也可以用这个恢复)

    异常处理汇总 ~ 修正果带着你的Net飞奔吧! http://www.cnblogs.com/dunitian/p/4599258.html 个人博客:http://dnt.dkill.net 下载下 ...

  7. SQL Server 错误日志过滤(ERRORLOG)

    一.背景 有一天我发现SQL Server服务器的错误日志中包括非常多关于sa用户的登陆错误信息:“Login failed for user 'sa'. 原因: 评估密码时出错.[客户端: XX.X ...

  8. Sql Server系列:数据表操作

    表是用来存储数据和操作数据的逻辑结构,用来组织和存储数据,关系数据库中的所有数据都表现为表的形式,数据表由行和列组成.SQL Server中的数据表分为临时表和永久表,临时表存储在tempdb系统数据 ...

  9. Android Studio使用技巧:导出jar包

    转自http://blog.csdn.net/lincyang/article/details/44457799 AS中并没有独立的Module 工程,但是可以在普通的Project中加入Module ...

  10. Android studio每次启动卡在fetching Android sdk compoment information的解决方案

    网上有人给出了方案:1)进入刚安装的Android Studio目录下的bin目录.找到idea.properties文件,用文本编辑器打开.2)在idea.properties文件末尾添加一行: d ...