【WCF】服务并发中的“可重入模式”
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】服务并发中的“可重入模式”相关推荐
- 【java】动态高并发时为什么推荐重入锁而不是Synchronized?
1.概述 转载:http://www.dreamwu.com/post-1758.html 这个图画的不错,有助于加深理解. [Java]Synchronized 有几种用法 [java] 从hots ...
- Linux中的可重入函数和不可重入函数
可重入函数 可重入函数(即可以被中断的函数)可以被一个以上的任务调用,而不担心数据破坏.可重入函数在任何时候都可以被中断,而一段时间之后又可以恢复运行,而相应的数据不会破坏或者丢失. 可重入函数使用的 ...
- 递归重入c语言延时函数多任务程序设计中的函数重入问题按照Keil的规范对函数添加关键字“reentrant”,将函数定义为可重入的 void Delay_MS(x) reentrant
c语言延时函数_子牙篇(2)多任务程序设计中的函数重入问题 weixin_39559333 2020-11-29 09:07:44 39 收藏 文章标签: c语言延时函数 c语言延时函数delay ...
- java可重入锁是什么意思_Java中的可重入(Reentrant)锁
## 什么是可重入锁? 可重入锁是一种特殊的互斥锁,它可以被同一个线程多次获取,而不会产生死锁. 1. 首先它是互斥锁:任意时刻,只有一个线程锁.即假设A线程已经获取了锁,在A线程释放这个锁之前,B线 ...
- java重入锁_java并发编程:可重入锁是什么?
释义 广义上的可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提得是同一个对象或者class),这样的锁就叫做可重入锁.ReentrantLock和sync ...
- Java并发编程实战————可重入内置锁
引言 在<Java Concurrency in Practice>的加锁机制一节中作者提到: Java提供一种内置的锁机制来支持原子性:同步代码块."重入"意味着获取 ...
- Java并发编程之ReentrantLock重入锁
ReentrantLock: 源码层面分析: public class ReentrantLock implements Lock, java.io.Serializable {private sta ...
- Java并发编程-ReentrantLock可重入锁
目录 1.ReentrantLock可重入锁概述 2.可重入 3.可打断 4.锁超时 5.公平锁 6.条件变量 Condition 1.ReentrantLock可重入锁概述 相对于 synchron ...
- RTOS中的可重入函数与不可重入函数
主要体现在实时操作系统(RTOS)中,即多任务环境中,经常会出现多个任务调用同一个函数的情况. 一.不可重入函数 1.概念 不可重入函数,即不能重复进入的函数,不能被中断的函数.在多个任务调用这个函数 ...
最新文章
- Ubuntu10.04各文件夹的作用
- 关于 Python 列表操作,最常见问答Top10
- leetcode 438. Find All Anagrams in a String | 438. 找到字符串中所有字母异位词(Java)
- war部署到tomcat
- 前端学习(1499):组件特点
- 95-242-040-源码-快照-Flink 分布式快照的设计-存储
- 5G 基站为何建得比 4G 多?
- 如何消灭 Android 应用中的广告?
- mangos服务器架构
- react的导出是怎么实现的_不到一百行代码,我们来实现一个简简简简简简简简简简版react库...
- Extjs 4.1 学习笔记(二)(panel 自适应高度)
- C++构造函数、new、delete
- java中日期做减法_Java中日期的加法和减法
- 444项国家标准3月1日起实施
- 微波工程基础_军工央企丨上海微波设备研究所
- Java培训后如何找工作?
- 市场爆发在即 分布式电站运维出路何在?
- C++判断系统位数(64位或32位)
- vb.net 实现图片圆形渐变模糊
- 普通人如何投资区块链才不亏?
热门文章
- hibernate中主键的生成策略
- uefi装原版win8.1怎么装|uefi gpt启动模式安装win8原版系统步骤
- C++ 标准文件的写入读出(ifstream,ofstream)
- Delphi 7连接MySql 5 5 15
- 区块链教程(五):合约编写实战实例
- Golang基本数据类型的相互转换
- python中grid函数_Python / NumPy中meshgrid的目的是什么?
- bat代码雨代码流星_bat-入门系列-03-判断结构2
- 实车采集的数据重建场景_避障、探测、采样......华理这套系统让无人小车“身手非凡”...
- git 32位_完整的GIT笔记 快速上手小白教程