化零为整WCF(12) - 并发和限流(Concurrent和Throttle)

[索引页]
[源码下载]


化零为整WCF(12) - 并发和限流(Concurrent和Throttle)


作者: webabcd


介绍
WCF(Windows Communication Foundation) - 并发(Concurrent):
    1、ConcurrencyMode.Single:单线程并发模式。系统自动加锁,无并发问题
    ·InstanceContextMode.PerCall:每个线程都会被分配一个新的实例
    ·InstanceContextMode.PerSession:每个Session被分配一个新的实例,每个Session内同时只会有一个线程操作实例
    ·InstanceContextMode.Single:唯一实例,并发调用只会有一个线程操作实例
    2、ConcurrencyMode.Reentrant:可重入的单线程并发模式。有可重入(回调)操作时,此模式才会生效,从回调返回的线程会进入队列尾部排队
    ·InstanceContextMode.PerCall:每个线程都会被分配一个新的实例,当有回调操作时如果使用Single并发模式的话就会产生死锁(1、调用服务端;2、回调客户端;3、返回服务端,1的时候锁定了,到3的时候就无法执行了,所以死锁了),此时应该用Reentrant并发模式
    ·InstanceContextMode.PerSession:每个Session被分配一个新的实例,每个Session内同时只会有一个线程操作实例,Session内可重入
    ·InstanceContextMode.Single:唯一实例,并发调用只会有一个线程操作实例,全局可重入
    3、ConcurrencyMode.Multiple:多线程并发模式。系统不会自动加锁,有并发问题
    ·InstanceContextMode.PerCall:每个线程都会被分配一个新的实例,无并发问题
    ·InstanceContextMode.PerSession:每个Session被分配一个新的实例,每个Session内多线程操作实例的话会有并发问题
    ·InstanceContextMode.Single:唯一实例,允许多线程并发操作实例,有并发问题

WCF(Windows Communication Foundation) - 限流(Throttle):
     < behaviors >
        
< serviceBehaviors >
            
< behavior  name ="BehaviorPerCall" >
                
<!-- httpGetEnabled - 指示是否发布服务元数据以便使用 HTTP/GET 请求进行检索,如果发布 WSDL,则为 true,否则为 false,默认值为 false -->
                
< serviceMetadata  httpGetEnabled ="true" />
                
<!-- maxConcurrentCalls - 服务中同时存在的最大活动消息数,默认值为 16 -->
                
<!-- maxConcurrentInstances - 服务中同时存在的最大服务实例数,默认值为 Int32.MaxValue -->
                
<!-- maxConcurrentSessions - 服务中同时存在的最大会话数,默认值为 10 -->
                
< serviceThrottling  maxConcurrentCalls =""  maxConcurrentInstances =""  maxConcurrentSessions =""   />
            
</ behavior >
            
< behavior  name ="BehaviorPerSession" >
                
< serviceMetadata  httpGetEnabled ="true" />
                
< serviceThrottling  maxConcurrentCalls =""  maxConcurrentInstances =""  maxConcurrentSessions =""   />
            
</ behavior >
            
< behavior  name ="BehaviorSingle" >
                
< serviceMetadata  httpGetEnabled ="true" />
                
< serviceThrottling  maxConcurrentCalls =""  maxConcurrentInstances ="1"  maxConcurrentSessions =""   />
            
</ behavior >
        
</ serviceBehaviors >
    
</ behaviors >


示例(以ConcurrencyMode.Reentrant为例)
1、服务

IDuplexReentrant.cs
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

using  System.ServiceModel;

namespace  WCF.ServiceLib.Message
{
    
/// <summary>
    
/// IDuplexReentrant接口(演示ConcurrencyMode.Reentrant)
    
/// </summary>
    
/// <remarks>
    
/// IDuplexReentrantCallback - 回调接口
    
/// </remarks>

    [ServiceContract(CallbackContract = typeof(IDuplexReentrantCallback))]
    
public interface IDuplexReentrant
    
{
        
/// <summary>
        
/// Hello
        
/// </summary>
        
/// <param name="name">名字</param>

        [OperationContract]
        
void HelloDuplexReentrant(string name);
    }


    
/// <summary>
    
/// IDuplexReentrant回调接口
    
/// </summary>

    public interface IDuplexReentrantCallback
    
{
        
/// <summary>
        
/// Hello
        
/// </summary>
        
/// <param name="name"></param>

        [OperationContract]
        
void HelloDuplexReentrantCallback(string name);
    }

}


DuplexReentrant.cs
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

using  System.ServiceModel;

namespace  WCF.ServiceLib.Message
{
    
/// <summary>
    
/// DuplexReentrant类 (演示ConcurrencyMode.Reentrant)
    
/// </summary>
    
/// <remarks>
    
/// ConcurrencyMode - 获取或设置一个值,该值指示服务是支持单线程、多线程还是支持可重入调用。默认值为 System.ServiceModel.ConcurrencyMode.Single。
    
/// Single - 服务实例是单线程的,且不接受可重入调用。
    
/// Reentrant - 服务实例是单线程的,且接受可重入调用。
    
/// Multiple - 服务实例是多线程的。
    
/// </remarks>

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
    
public class DuplexReentrant : IDuplexReentrant
    
{
        
/// <summary>
        
/// Hello
        
/// </summary>
        
/// <param name="name">名字</param>

        public void HelloDuplexReentrant(string name)
        
{
            
// 声明回调接口
            IDuplexReentrantCallback callback = OperationContext.Current.GetCallbackChannel<IDuplexReentrantCallback>();

            
// 调用回调接口中的方法
            callback.HelloDuplexReentrantCallback(name);
        }

    }

}



2、宿主
DuplexReentrant.cs
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

using  System.ServiceModel;

namespace  WCF.ServiceHost2.Message
{
    
/// <summary>
    
/// host WCF.ServiceLib.Message.DuplexReentrant的类
    
/// </summary>

    public class DuplexReentrant
    
{
        
/// <summary>
        
/// 启动WCF.ServiceLib.Message.DuplexReentrant服务
        
/// </summary>

        public void Launch()
        
{
            
using (ServiceHost host = new ServiceHost(typeof(WCF.ServiceLib.Message.DuplexReentrant)))
            
{
                host.Open();

                Console.WriteLine(
"服务已启动(WCF.ServiceLib.Message.DuplexReentrant)");
                Console.WriteLine(
"按<ENTER>停止服务");
                Console.ReadLine();

            }

        }

    }

}


App.config
<? xml version="1.0" encoding="utf-8"  ?>
< configuration >
    
< system.serviceModel >
        
< services >
            
<!-- name - 提供服务的类名 -->
            
<!-- behaviorConfiguration - 指定相关的行为配置 -->
            
< service  name ="WCF.ServiceLib.Message.DuplexReentrant"  behaviorConfiguration ="MessageBehavior" >
                
<!-- address - 服务地址 -->
                
<!-- binding - 通信方式 -->
                
<!-- contract - 服务契约 -->
                
< endpoint  address ="Message/DuplexReentrant"  binding ="netTcpBinding"  contract ="WCF.ServiceLib.Message.IDuplexReentrant"   />
                
< endpoint  address ="mex"  binding ="mexHttpBinding"  contract ="IMetadataExchange"   />
                
< host >
                    
< baseAddresses >
                        
< add  baseAddress ="http://localhost:12345/Message/DuplexReentrant" />
                        
< add  baseAddress ="net.tcp://localhost:54321/" />
                    
</ baseAddresses >
                
</ host >
            
</ service >
        
</ services >
        
< behaviors >
            
< serviceBehaviors >
                
< behavior  name ="MessageBehavior" >
                    
<!-- httpGetEnabled - 指示是否发布服务元数据以便使用 HTTP/GET 请求进行检索,如果发布 WSDL,则为 true,否则为 false,默认值为 false -->
                    
< serviceMetadata  httpGetEnabled ="true"   />
                    
< serviceDebug  includeExceptionDetailInFaults ="true" />
                
</ behavior >
            
</ serviceBehaviors >
        
</ behaviors >
    
</ system.serviceModel >
</ configuration >


3、客户端
DuplexReentrant.cs
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

using  System.ServiceModel;
using  System.Windows.Forms;

namespace  Client2.Message
{
    
/// <summary>
    
/// 演示Message.DuplexReentrant的类
    
/// </summary>

    public class DuplexReentrant
    
{
        
/// <summary>
        
/// Hello
        
/// </summary>
        
/// <param name="name">名字</param>

        public void HelloDulexReentrant(string name)
        
{
            var ct 
= new Client2.Message.ReentrantCallbackType();
            var ctx 
= new InstanceContext(ct);

            var proxy 
= new MessageSvc.DuplexReentrant.DuplexReentrantClient(ctx);

            proxy.HelloDuplexReentrant(name);
        }

    }

}


ReentrantCallbackType.cs
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

using  System.Windows.Forms;

namespace  Client2.Message
{
    
/// <summary>
    
/// 实现回调接口
    
/// </summary>
    
/// <remarks>
    
/// CallbackBehavior - 在客户端应用程序中配置回调服务实现
    
/// UseSynchronizationContext - 如果对服务的所有调用都必须在 System.Threading.SynchronizationContext 指定的线程上运行,则为 true;否则为false。默认值为 true。
    
/// </remarks>

    [System.ServiceModel.CallbackBehavior(UseSynchronizationContext = false)]
    
public class ReentrantCallbackType : MessageSvc.DuplexReentrant.IDuplexReentrantCallback
    
{
        
/// <summary>
        
/// Hello
        
/// </summary>
        
/// <param name="name">名字</param>

        public void HelloDuplexReentrantCallback(string name)
        
{
            MessageBox.Show(
"Hello: " + name);
        }

    }

}


App.config
<? xml version="1.0" encoding="utf-8"  ?>
< configuration >
    
< system.serviceModel >
        
< client >
            
< endpoint  address ="net.tcp://localhost:54321/Message/DuplexReentrant"
                binding
="netTcpBinding"  contract ="MessageSvc.DuplexReentrant.IDuplexReentrant" >
            
</ endpoint >
        
</ client >
    
</ system.serviceModel >
</ configuration >


运行结果:
单击"btnDuplexReentrant"按钮后弹出提示框,显示"Hello: webabcd"


OK
[源码下载]

你可能感兴趣的:(Concurrent)