WCF死锁三种不同方式介绍

用过WCF的朋友们应该会清楚的认识到,当我们在使用回调契约时,通常会出现死锁的情况出现。那么如何才能正确的解决WCF死锁问题呢?我们今天就为大家详细介绍了几种解决方案,供大家参考学习。#t#

创新互联拥有一支富有激情的企业网站制作团队,在互联网网站建设行业深耕10余年,专业且经验丰富。10余年网站优化营销经验,我们已为上千多家中小企业提供了成都网站制作、网站建设解决方案,按需网站建设,设计满意,售后服务无忧。所有客户皆提供一年免费网站维护!

例如,当客户端执行服务操作时,向客户端发出的调用会阻塞服务端进程,以等待服务操作执行完毕。而在该服务操作中,又获得了回调契约对象的引用(或者获得保存的回调契约副本),并执行回调操作。由于服务类被配置为单线程访问,则服务实例是与锁相关联的。如果回调对象也需要返回同一个锁的所有权,简单的说,就是指当回调的应答消息也需要获得与服务实例关联的相同的锁时,就会导致死锁。因为此时服务线程已经被阻塞,服务操作正在等待回调操作执行完毕,而回调操作却又在等待服务释放锁,自然会产生锁的争用。

解决WCF死锁的办法有三个,一个是将服务配置为允许多线程访问,但这会增加服务开发者管理多线程的负担。第二个方案是将回调设置为重入(Reentrancy),如下所示:

 
 
 
  1. [ServiceBehavior(ConcurrencyModeConcurrencyMode = 
    ConcurrencyMode.Reentrant)]   
  2. class MyService : IMyContract   
  3. {   
  4. public void DoSomething( )   
  5. {   
  6. IMyContractCallback callback = OperationContext.Current. 
    GetCallbackChannel( );  
  7. callback.OnCallback( );   
  8. }   
  9. }   
  10.  

所谓“重入”,是指对同步域拥有独占访问权的线程A调用了同步域之外对象的方法,此时,另外的线程B若要访问该同步域,则线程A将释放对同步域的锁,允许线程B进入。直到线程B执行完毕并释放对同步域的锁后,线程A将重新进入该同步域。配置回调为重入时,因为服务对象是与线程关联的,属于同步域的对象,而回调对象则属于同步域之外的对象。由于服务被配置为重入,则服务调用回调引用时会释放锁。然后将回调返回给客户端,控制权则返回给服务,服务会重入并重新获取锁。这样就解决了死锁的问题。

第三种方案则是将回调操作设置为单向操作。此时,回调调用不会产生应答消息,服务操作一旦执行了回调操作,就会继续执行,回调对象不会争用与服务实例关联的锁,从而解决了WCF死锁问题。

 
 
 
  1. interface IMyContractCallback   
  2. {   
  3. [OperationContract(IsOneWay = true)] void OnCallback( );   
  4. }  

在使用回调对象时,需要考虑到客户端代理可能会被关闭,如果此时调用回调,就会引发一个ObjectDisposedException异常。“因此,对于客户端而言,当它不再需要接收回调或者客户端应用程序已经关闭时,***能够通知服务。”本书给出了解决这一问题的方法,就是为服务契约增加两个操作Connect()与Disconnect()。其中,Disconnect()正是起到了通知服务的作用,它在客户端代理关闭的情况下,可以将当前的回调对象引用从列表中移除。至于Connect()方法则是出于对称的目的而引入,但引入它还有一个好处是,它可以使得客户端能够多次地连接或断开。实现Connect()与Disconnect()方法的代码如下:

 
 
 
  1. static List m_Callbacks = 
    new List( );   
  2. public void Connect( ) {   
  3. IMyContractCallback callback = OperationContext.Current. 
    GetCallbackChannel( );   
  4. if(m_Callbacks.Contains(callback) == false)   
  5. {   
  6. m_Callbacks.Add(callback);   
  7. }   
  8. }   
  9. public void Disconnect( )   
  10. {   
  11. IMyContractCallback callback = OperationContext.Current. 
    GetCallbackChannel( );   
  12. if(m_Callbacks.Contains(callback) == true)   
  13. {   
  14. m_Callbacks.Remove(callback);   
  15. }   
  16. else   
  17. {   
  18. throw new InvalidOperationException("Cannot find callback");   
  19. }   
  20. }  

以上就是我们为大家介绍的几种不同的WCF死锁解决方法。

文章名称:WCF死锁三种不同方式介绍
文章链接:http://www.hantingmc.com/qtweb/news30/126830.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联