《WCF按部就班学习系列8_WCF并发管理概述》(下)

【7】ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,InstanceContextMode = InstanceContextMode.PerCall) --Multiple并发与PerCall实例模型
1.图8-16单调模型和多线程模型描述

《WCF按部就班学习系列8_WCF并发管理概述》(下)_第1张图片

2.对于Multiple并发模型,应当是多线程的并发访问模式,但对于PerCall实例模型中,每个线程与一个独立的服务实例进行交互,所以一般不会产生并发冲突。但如果服务实例中使用了静态变量或全局数据缓存的时候,在多线程操作这些共享资源时需要手动编写同步代码,以确保这些共享资源不会发生并发冲突。
3.要想防止多个服务实例对静态变量修改操作产生并发冲突,需要我们手写代码对它进行同步保护。
服务端代码做如下修改
public class MultiplePerCall : IMultiplePerCall { ...... while (true) { lock (typeof(MultiplePerCall)) { .... } } }
4.使用lock语句段,把变量修改与显示的代码锁定在一起,防止其实服务实例的并发修改冲突。
5.图8-17单调模型和多线程模型运行结果 

《WCF按部就班学习系列8_WCF并发管理概述》(下)_第2张图片

【8】ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,InstanceContextMode = InstanceContextMode.PerSession) --Multiple并发与PerSession实例模型
1.图8-18会话模型和多线程模型描述

《WCF按部就班学习系列8_WCF并发管理概述》(下)_第3张图片

2.“Multiple并发+PerSession实例模型”会对每个客户端的多线程请求指派一个服务实例进行处理,多线程的请求同一个服务时,同样并不会自动锁定该服务,对于服务中的数据进行修改的时候也需要我们手动编写同步代码进行保护。
3.图8-19会话模型和多线程运行结果

4.从图8-19中我们看出,服务端的确有两个服务在运行(42931033和20974680),这两个服务实例分别出现了一次数据重复。并且是同一服务实例内的数据重复,即说明了同一客户端的多线程

调用发生了并发冲突。防止并发冲突的同步锁定代码:
   lock (this)
    {
       ...
    }
【9】ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,InstanceContextMode = InstanceContextMode.Single) --Multiple并发与Single实例模型
1.图8-20单例模型和多线程模型描述

2.这种并发模型与实例模型的匹配算是多线程并发操作的一个极佳搭配。在Single实例模型中,所有客户端的所有线程共享一个服务实例,这样可以很好地解决多个客户端的不同线程间的状态共享的问题。可是这种实例模型的吞吐量会小于PerCall实例模型的吞吐量,因此我们可以使用Multiple并发模型来增加其吞吐量,可以允许多个客户端线程对服务实例同时调用。但这样也最容易对一些共享数据和共享资源引起并发冲突,所以需要我们手动编写代码对共享数据和共享资源进行并发保护。
3.图8-21单例模型和多线程模型运行结果

4.从上面图8-21中看出,服务端只有一个服务实例,三个线程同时运行,产生并发冲突。
5.总结上面的内容,增加系统吞吐量可以提升服务的效率。但影响吞吐量的因素比较多,如:实例模型、并发模型和调用模型等。
2.3限流
1.可以配置服务行为的serviceThrottling属性来对WCF服进行限流。
MaxConcurrentCalls:限制客户端发起的并发请求数量 – 缺省为16
MaxConcurrentInstances:限制服务端服务实例的数量。
MaxConcurrentSessions:限制活动会话数量-缺省值10
2.配置代码如下
<behaviors> <serviceBehaviors> <behavior name="NewBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceThrottling maxConcurrentCalls="20" maxConcurrentSessions="10" maxConcurrentInstances="30"/> </behavior> </serviceBehaviors> </behaviors>
(3)实现代码分析及运行结果
3.1WCFService(服务端源码分析)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; namespace WCFService { //服务契约 [ServiceContract] public interface ISinglePerCall { //操作契约 [OperationContract] int GetValue1(); [OperationContract] int GetValue2(); } //单调模型和单线程模式 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)] public class SinglePerCall:ISinglePerCall,IDisposable { private int InstanceVariable = 0; private static int StaticVariable = 0; public int GetValue1() { Console.WriteLine("GetValue1(),{0}",++ InstanceVariable); return ++InstanceVariable; } public int GetValue2() { Console.WriteLine("GetValue1(),{0}" ,++StaticVariable); return ++StaticVariable; } public void Dispose() { Console.WriteLine("dispose()"); } } }

3.2WCFHost(宿主源码分析和运行结果)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; namespace WCFHost { public class Program { static void Main(string[] args) { //判断是否打开连接,如果没有则打开侦听 ServiceHost host = new ServiceHost(typeof(WCFService.SinglePerCall), new Uri("http://localhost:8000/")); if (host.State != CommunicationState.Opened) { host.Open(); } //显示运行状态 Console.WriteLine("host is running ,the state is {0}", host.State); Console.ReadKey(); } } }

运行结果见图8-22服务器运行结果

3.3WCFClient(客户端源码分析和运行结果)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Threading; namespace WCFClient { public class Program { public static SinglePerCallClient client = new SinglePerCallClient(); static void Main(string[] args) { //循环6次 for (int i = 0; i < 6; i++) { Thread thread = new Thread(new ThreadStart(DoWork)); thread.Start(); while (!thread.IsAlive) ; } } public static void DoWork() { //输出当前线程的hash编码值和wcf服务端实例变量值与静态变量值比较 Console.WriteLine("线程" + Thread.CurrentThread.GetHashCode() + ":/t实例变量的值" + client.GetValue1()); Console.WriteLine("线程" + Thread.CurrentThread.GetHashCode() + ":/t静态变量的值" + client.GetValue2()); Console.ReadKey(); } } }

运行结果见图8-23客户端运行结果

《WCF按部就班学习系列8_WCF并发管理概述》(下)_第4张图片

(4)源码下载
http://download.csdn.net/source/3054422
(5)下一篇计划
下一篇主要介绍WCF中队列服务的相关知识。
(6)参考说明
1.《Programming WCF Services》
2.http://hi.baidu.com/grayworm

 

你可能感兴趣的:(thread,多线程,String,Class,WCF,代码分析)