刚刚吃完饭,,很饱很饱..感谢兄弟伙了..我都记在心里
传入客户端调用都会被分发到windows线程池做统一处理,在使用时我们还必要要提供线程安全访问等过程..
这就可能要设计到线程同步的问题了,WCF提供了两种关于线程同步的方案 1.自动同步 2.手动同步(可能需要大家付出更多的代码来维护服务的状态了)
1.自动同步
这种方式比较简单,是在我们的服务行为(ServiceBehavior)中进行管理 [ConcurrencyMode]
这个声明式标签有三个属性值,其分别是 Single(单例),Reentrant(单例),Multiple(并发)
Single没什么还说的,重点看一下Reentrant的服务重入与Multiple的并发锁定
服务在配置成Reentrant模式时,最好是使用回调契约无返回值的情况,我们知道单例模式的操作,当服务被调用时WCF会锁定上下文资源对象
这样的话我们再去使用回调函数,当回调函数返回后,就可能会造成服务死锁的状况...这也是使用Reentrant模式的意义所在,这种定义可以在服务重入的时候重新加锁锁定资源...
服务在配置成Multiple模式时,其实使用Monitor锁定(lock)局部对象还是会发生死锁问题,试想如果锁定整个方法主体呢?个人认为这样的锁定不灵活,颗粒度也过于粗,没有意义了...ms也想到了此问题,最佳的解决方案就是直接引入编译器!,
利用编译器将我们的调用对象自动对实例加锁
[MethodImpl(MethodImplOptions.Synchronized)],不过问题还没有结束,,如果我的部分方法不需要同步访问呢?当然我们还可以
[ReleaseServiceInstanceOnTransactionComple=false],这样就可以完美的解决在并发中的同步问题了
注: 当然使用服务类型共享锁也是可以解决死锁问题的.
2.手动同步
在手动同步中,我们可能更多的要和同步上下文打交道了SynchronizationContext , 注:同步上下文使用没有确定的object对象,不是类型安全的对象,使用时需要注意.
封装同步上下文示意
class MyResource
{
SynchronizationContext MySynchronizationContext;
public int DoWork()
{
int result = 0;
SendOrPostCallBack doWork = delegate { result = DoWorkInternal(); }
MySynchronizationContext.Send(doWork,null);
return result;
}
int DoWorkInternal()
{
return 2;
}
}
class MyService : IMyContract
{
MyResource GetResource()
{
return new MyResource();
}
public void MyMethod()
{
MyResource resource = GetResource();
int result = resource.DoWork();
}
}
异步调用需要使用IAsycnResult接口,注意的是实现此接口调用服务的话,需要传入ref标识同步值,InterLocker调用去处理标识同步值
轮询或等待完成,需要使用到异步对象的AsyncWaitHandle的WaitOne与WaitAll方法,
本文转自My_King1 51CTO博客,原文链接:http://blog.51cto.com/apprentice/1360555,如需转载请自行联系原作者