化零为整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):
示例(以ConcurrencyMode.Reentrant为例)
1、服务
IDuplexReentrant.cs
DuplexReentrant.cs
2、宿主
DuplexReentrant.cs
App.config
3、客户端
DuplexReentrant.cs
ReentrantCallbackType.cs
App.config
运行结果:
单击"btnDuplexReentrant"按钮后弹出提示框,显示"Hello: webabcd"
OK
[源码下载]
[源码下载]
化零为整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>
<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);
}
}
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);
}
}
}
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();
}
}
}
}
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>
<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);
}
}
}
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);
}
}
}
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>
<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
[源码下载]