WCF死锁三种不同方式介绍

开发 开发工具
我们今天在这篇文中为大家总结了三种比较常用的解决WCF死锁问题的相关方法,希望能够帮助朋友们在实际开发中解决问题。

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

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

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

 

  1. [ServiceBehavior(ConcurrencyModeConcurrencyMode = 
    ConcurrencyMode.Reentrant)]   
  2. class MyService : IMyContract   
  3. {   
  4. public void DoSomething( )   
  5. {   
  6. IMyContractCallback callback = OperationContext.Current. 
    GetCallbackChannel
    <IMyContractCallback>( );  
  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<IMyContractCallback> m_Callbacks = 
    new List<IMyContractCallback>( );   
  2. public void Connect( ) {   
  3. IMyContractCallback callback = OperationContext.Current. 
    GetCallbackChannel
    <IMyContractCallback>( );   
  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
    <IMyContractCallback>( );   
  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死锁解决方法。

责任编辑:曹凯 来源: IT168
相关推荐

2010-02-04 10:33:40

C++异常传递

2010-02-26 13:34:50

WCF编码机制

2010-02-23 14:24:50

WCF状态保存

2010-02-23 09:58:21

WCF客户端验证

2018-12-01 09:15:47

物联网设备物联网IOT

2009-11-06 10:54:19

WCF服务方式

2009-08-20 17:30:02

C#连接字符串

2009-11-06 13:23:27

WCF模式

2019-12-09 10:30:42

Windows 10帐户Windows

2011-07-22 17:22:20

Spring

2009-12-21 13:37:43

WCF消息交换

2012-07-17 09:16:16

SpringSSH

2009-08-06 15:26:18

C#异常类型

2009-12-22 15:14:33

WCF调用

2010-02-22 14:18:34

WCF服务验证

2010-03-12 17:52:35

Python输入方式

2009-12-22 13:34:07

WCF性能计数器级别

2010-04-20 12:00:01

负载均衡技术

2010-06-13 16:04:14

MySQL三种安装方式

2020-11-01 17:10:46

异步事件开发前端
点赞
收藏

51CTO技术栈公众号