WCF服务实例的并发模式是在服务实现类上,使用 ServiceBehaviorAttribute 的 ConcurrencyMode 属性来指定。其值由 ConcurrencyMode 枚举来界定,这个枚举只有三个值:

Single——服务实例只在单个线程上运行,如果服务是单个实例,那么同一时间只有一个传入的调用被接收,其他调用请拿票排队。

Multiple——这个好理解,服务实例支持多个线程同时调用,所以状态数据可能会不同步(单个服务实例),如果某些变量担心被其他线程意外修改,可以适合地 lock 一下。

Reentrant——这家伙是今天的主角,因为它不太好理解。老周就不抄MSDN了,就按我自己的理解说一下。“可重入模式”大致是这个意思:首先,服务实例是单线程,但是,如果在服务中调用另外的服务,那么此时其他正在排队的传入消息就可以进来。等其他另一个服务调用完成后,又重新进入当前服务操作继续向下执行。有点像你去营业厅排队办业务,服务窗口中的工作人员就是服务实例,而窗口外面排队的客户就是等待调用的客户端。假如我要申请一个业务,通常要填个XXX表格。要是等你填完,估计后面排队的人会跑掉一半。所以,常规的做法是:你站到一边去填表(相当于在服务实例中调用另外一个服务),然后让后面排队的人继续办业务。等你填完表了,再回来找工作人员处理(相当于另外一个服务调用完成,重新进入当前服务实例)。

没看懂?还是实例好用吧。来,下面咱们来动动手吧。

首先我们弄个“另一个”服务。

    [ServiceContract]public interface ISome{[OperationContract]Guid GetUID();}class SomeService : ISome{public Guid GetUID(){Guid id = Guid.NewGuid();Console.WriteLine($"第二个服务被调用,产生的ID为:{id}");return id;}}

这个服务协定有一个方法,作用很简单,产生一个GUID,然后返回,能看懂吧。

好,现在来弄“主”服务。

    [ServiceContract]public interface ITestService{[OperationContract]void TestCall();}

待会儿我们实现这个协定时,在服务操作方法中去调用前面的“另一个”服务。

    internal class TestService : ITestService{public void TestCall(){Console.WriteLine("即将调用另一个服务。");// 调用其他服务ISome cnl = ChannelFactory<ISome>.CreateChannel(new BasicHttpBinding(), new EndpointAddress("http://localhost:12345"));// 调用完成后,再次回来Guid id = cnl.GetUID();((IClientChannel)cnl).Close();Console.WriteLine($"回到当前服务。得到的ID为:{id}");}}

还没完呢,我们设置一下这个服务类,让它使用“可重入”并发模式。

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)]internal class TestService : ITestService{……}

启动ServiceHost并接收请求。

            using (ServiceHost host = new ServiceHost(typeof(TestService))){host.AddServiceEndpoint(typeof(ITestService), new WSHttpBinding(), "http://localhost:9000");host.Open(); //运行服务Console.WriteLine("主服务已启动。");……Console.ReadKey();}

模拟客户端调用,咱们开N个 Task 来模拟同时有 N 个客户端调用服务的情形。

                Action actdlg = () =>{ITestService cn = ChannelFactory<ITestService>.CreateChannel(new WSHttpBinding(), new EndpointAddress("http://localhost:9000"));cn.TestCall();// 关闭通道
                      ((IClientChannel)cn).Close();};// 开启5个任务Task[] tasks = new Task[5];// 初始化每个任务for (int n = 0; n < tasks.Length; n++){tasks[n] = new Task(actdlg);}// 开始执行任务foreach (Task t in tasks){t.Start();}// 等待所有任务完成Task.WaitAll(tasks);

最后的 Task.WaitAll 用以等待所有 Task 完成执行,此处可以不要这句。

好,见证的时刻即将来了。运行!

在当前服务去调用另外一个服务的时候,其他正在等待的调用就会进来,在上图中,上面的是“另一个”服务被调用时生成的 GUID,下面是“另一个”服务调用完成后返回到当前服务后得到的 GUID。

从图中,大家会发现,“另一个”服务产生ID输出的顺序,与调用返回后输出的顺序不同,看来,调用完成后,重新进入到当前服务实例的消息还得排队,故调用后返回的消息顺序与“另一个”服务生成ID的顺序并不一致。

不知道用这个示例来装逼之后,各位是否能理解“可重入”并发的含义。

示例源代码下载地址

转载于:https://www.cnblogs.com/tcjiaan/p/6434673.html

【WCF】服务并发中的“可重入模式”相关推荐

  1. 【java】动态高并发时为什么推荐重入锁而不是Synchronized?

    1.概述 转载:http://www.dreamwu.com/post-1758.html 这个图画的不错,有助于加深理解. [Java]Synchronized 有几种用法 [java] 从hots ...

  2. Linux中的可重入函数和不可重入函数

    可重入函数 可重入函数(即可以被中断的函数)可以被一个以上的任务调用,而不担心数据破坏.可重入函数在任何时候都可以被中断,而一段时间之后又可以恢复运行,而相应的数据不会破坏或者丢失. 可重入函数使用的 ...

  3. 递归重入c语言延时函数多任务程序设计中的函数重入问题按照Keil的规范对函数添加关键字“reentrant”,将函数定义为可重入的 void Delay_MS(x) reentrant

    c语言延时函数_子牙篇(2)多任务程序设计中的函数重入问题 weixin_39559333 2020-11-29 09:07:44  39  收藏 文章标签: c语言延时函数 c语言延时函数delay ...

  4. java可重入锁是什么意思_Java中的可重入(Reentrant)锁

    ## 什么是可重入锁? 可重入锁是一种特殊的互斥锁,它可以被同一个线程多次获取,而不会产生死锁. 1. 首先它是互斥锁:任意时刻,只有一个线程锁.即假设A线程已经获取了锁,在A线程释放这个锁之前,B线 ...

  5. java重入锁_java并发编程:可重入锁是什么?

    释义 广义上的可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提得是同一个对象或者class),这样的锁就叫做可重入锁.ReentrantLock和sync ...

  6. Java并发编程实战————可重入内置锁

    引言 在<Java Concurrency in Practice>的加锁机制一节中作者提到: Java提供一种内置的锁机制来支持原子性:同步代码块."重入"意味着获取 ...

  7. Java并发编程之ReentrantLock重入锁

    ReentrantLock: 源码层面分析: public class ReentrantLock implements Lock, java.io.Serializable {private sta ...

  8. Java并发编程-ReentrantLock可重入锁

    目录 1.ReentrantLock可重入锁概述 2.可重入 3.可打断 4.锁超时 5.公平锁 6.条件变量 Condition 1.ReentrantLock可重入锁概述 相对于 synchron ...

  9. RTOS中的可重入函数与不可重入函数

    主要体现在实时操作系统(RTOS)中,即多任务环境中,经常会出现多个任务调用同一个函数的情况. 一.不可重入函数 1.概念 不可重入函数,即不能重复进入的函数,不能被中断的函数.在多个任务调用这个函数 ...

最新文章

  1. Ubuntu10.04各文件夹的作用
  2. 关于 Python 列表操作,最常见问答Top10
  3. leetcode 438. Find All Anagrams in a String | 438. 找到字符串中所有字母异位词(Java)
  4. war部署到tomcat
  5. 前端学习(1499):组件特点
  6. 95-242-040-源码-快照-Flink 分布式快照的设计-存储
  7. 5G 基站为何建得比 4G 多?
  8. 如何消灭 Android 应用中的广告?
  9. mangos服务器架构
  10. react的导出是怎么实现的_不到一百行代码,我们来实现一个简简简简简简简简简简版react库...
  11. Extjs 4.1 学习笔记(二)(panel 自适应高度)
  12. C++构造函数、new、delete
  13. java中日期做减法_Java中日期的加法和减法
  14. 444项国家标准3月1日起实施
  15. 微波工程基础_军工央企丨上海微波设备研究所
  16. Java培训后如何找工作?
  17. 市场爆发在即 分布式电站运维出路何在?
  18. C++判断系统位数(64位或32位)
  19. vb.net 实现图片圆形渐变模糊
  20. 普通人如何投资区块链才不亏?

热门文章

  1. hibernate中主键的生成策略
  2. uefi装原版win8.1怎么装|uefi gpt启动模式安装win8原版系统步骤
  3. C++ 标准文件的写入读出(ifstream,ofstream)
  4. Delphi 7连接MySql 5 5 15
  5. 区块链教程(五):合约编写实战实例
  6. Golang基本数据类型的相互转换
  7. python中grid函数_Python / NumPy中meshgrid的目的是什么?
  8. bat代码雨代码流星_bat-入门系列-03-判断结构2
  9. 实车采集的数据重建场景_避障、探测、采样......华理这套系统让无人小车“身手非凡”...
  10. git 32位_完整的GIT笔记 快速上手小白教程