wcf并发行为是用于管理被关联到同一服务实例上的不同消息的处理,也可以理解为同一个客户端代理发送的多个请求,同一个服务实例怎么处理。
WCF中有三种并发行为可以设置。
single=0 默认设置
Reentrant=1
Multiple=2
1. Single模式
Single是默认的并发模式是默认的并发设置,WCF服务实例会为客户端的每一个请求提供同步锁,服务实例一次只能处理一个请求,多余的请求需要排队等待,类似于串行执行,不能并行。如果在排队等待的过程中,有一个请求等待超时,客户端将抛出异常。
下面的代码用多线程演示了客户端的同一个代理发送多个请求,服务器只能按顺序排队处理。上一个请求执行完成后,才能处理下一个请求的信息。
服务器端契约
[ServiceContract]
public interface ISingle
{
[OperationContract]
void SendMsg(string msg);
}
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Single)]
public class SingleImpl:ISingle,IDisposable
{
public void Dispose()
{
Console.WriteLine("释放实例");
}
public void SendMsg(string msg)
{
Console.WriteLine("开始"+msg);
System.Threading.Thread.Sleep(3000);
Console.WriteLine("完成"+msg);
Console.WriteLine("----------------------------");
}
}
客户端代码,客户端采用异步方式调用,调用WCF服务的时候,我们选择生成异步操作
private void button1_Click(object sender, EventArgs e)
{
SingleService.SingleClient client = new SingleService.SingleClient();
for (int i = 0; i < 5; i++)
{
client.BeginSendMsg(i.ToString(), new AsyncCallback(CallBackSendMsg), null);
}
}
void CallBackSendMsg(IAsyncResult ar)
{
Console.WriteLine("返回结果");
}
执行结果
2. MultiPle模式
Multiple模式允许一个客户端代理进行多线程访问,实现了并发访问,提高了系统处理效率,只需要对关键性资源加锁就可以了。把锁放在了系统的最小范围内。
下面的代码使用multiple模式展示了客户端代理使用多线程进行异步访问操作。
服务器端契约
[ServiceContract]
public interface IMultiple
{
[OperationContract]
void SendMsg(string msg);
}
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MultipleImpl:IMultiple,IDisposable
{
public void Dispose()
{
Console.WriteLine("释放实例");
}
public void SendMsg(string msg)
{
Console.WriteLine("开始" + msg);
System.Threading.Thread.Sleep(3000);
Console.WriteLine("结束" + msg);
}
}
客户端
void CallBackSendMsg(IAsyncResult ar)
{
Console.WriteLine("返回结果");
}
private void button2_Click(object sender, EventArgs e)
{
MultiService.MultipleClient client = new MultiService.MultipleClient();
for (int i = 0; i < 5; i++)
{
client.BeginSendMsg(i.ToString(), new AsyncCallback(CallBackSendMsg), null);
}
}
执行结果
3.Reentrant模式
Reentrant模式和single模式一样,也是单线程访问操作,但是是有区别的,当同一个客户端向服务器发送请求时候,服务器端客户回调客户端的操作,不会造成死锁,这样在一些耗时的服务操作中,能够提高服务实例的处理速度和吞吐量。这个主要是为双工模式服务的。
服务器契约
[ServiceContract(CallbackContract=typeof(ICallBack))]
public interface IReentrant
{
[OperationContract]
void SendMsg(string msg);
}
public interface ICallBack
{
[OperationContract]
string GetResult(string msg);
}
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]
public class ReentrantImpl:IReentrant,IDisposable
{
public void SendMsg(string msg)
{
Console.WriteLine("开始"+msg);
System.Threading.Thread.Sleep(3000);
ICallBack callback = OperationContext.Current.GetCallbackChannel<ICallBack>();
callback.GetResult(msg);
Console.WriteLine("结束"+msg);
}
public void Dispose()
{
Console.WriteLine("释放实例");
}
}
客户端
private void button3_Click(object sender, EventArgs e)
{
InstanceContext instanceContext = new InstanceContext(new CallBackService());
ServiceReen.ReentrantClient client = new ServiceReen.ReentrantClient(instanceContext);
for (int i = 0; i < 5; i++)
{
//client.BeginSendMsg(i.ToString(), new AsyncCallback(CallBackSendMsg), null);
client.SendMsg(i.ToString());
}
}
}
public class CallBackService : ServiceReen.IReentrantCallback
{
#region IReentrantCallback 成员
public string EndGetResult(IAsyncResult result)
{
throw new NotImplementedException();
}
#endregion
#region IReentrantCallback 成员
public string GetResult(string msg)
{
Console.WriteLine("返回结果"+msg);
return msg;
}
public IAsyncResult BeginGetResult(string msg, AsyncCallback callback, object asyncState)
{
throw new NotImplementedException();
}
#endregion
}
执行结果