明确的说WCF需要及时关闭

  刚学WCF的时候没发现这个问题,调得很愉快却没有发现其实“暗藏杀机”,可谓危险重重,还好后来觉得是有些不妥,于是google“WCF需要关闭吗”,立马找到了几个博客园的链接,进去一看,各位大侠均纷纷表示“关是一定要关的,但是你还不能用完就关,因为关了,就不能再打开了,还得New,可以New的成本又有一点高”,好吧,这么说来就只有好好规划一下了。

  那么什么时候该关呢,答案是异常了的时候,MSDN给出了代码(错误处理部分,找不到链接了,见谅)

 

      catch (CommunicationException)
            {
                client.Abort();
            
}
            
catch (TimeoutException)
            {
                clent.Abort();
            
}

 所以这样一来,就有了解决方案,那就是在每一处需要调用Wcf和代码里加上try catch,大概就成了如下这样

 

UserClient client  =   new  UserClient();
try
{
client.Create(
new  User(){
     UserName
= " xian " ,
     Password
= " 123 " });
}
catch (CommunicationException)
{
   client.Abort();
}
catch (TimeoutException)
{
   clent.Abort();
}

   这样挺好的,没错,不过我们总不可能只调用一个Wcf接口吧,我们要调的可是一系列,也就是若干接口,那么就我们就需要写很多重复的错误处理代码块了。这样原来没什么问题,而且是理所当然的事情。可是我记得某位老鸟说过当代码出现很大程度重复的时候你就该重构它了(也是在博客园看到了,很普通但深入人心的道理),并且为了让代码好看一点,我们还是想想好点的办法。

如果你有些经验,肯定马上就去想到使用委托来实现消除代码的冗余,是的,下面就是我这次的实现方式,代码如下: 

  

ServiceInvokeHelper调用辅助类
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.ServiceModel;

namespace  Helper
{
    
///   <summary>
    
///  Wcf服务调用辅助类
    
///   </summary
    public static class ServiceInvokeHelper <TChannel>  where TChannel : ICommunicationObject, new()
    {
        
#region  private fields
        
private   static  Dictionary < string , TChannel >  _ChannelDic  =   new  Dictionary < string , TChannel > ();
        
private   static   object  _Lockhelper  =   new   object ();

        
private   static  TResult TryFunc < TResult > (Func < TChannel, TResult >  func, TChannel channel)
        {
            
string  tChannelName  =   typeof (TChannel).FullName;
            
try
            {
                
return  func(channel);
            }
            
catch  (CommunicationException)
            {
                channel.Abort();
                
lock  (_Lockhelper)
                    _ChannelDic.Remove(tChannelName);
                
throw ;
            }
            
catch  (TimeoutException)
            {
                channel.Abort();
                
lock  (_Lockhelper)
                    _ChannelDic.Remove(tChannelName);
                
throw ;
            }
            
catch  (Exception)
            {
                channel.Abort();
                
lock  (_Lockhelper)
                    _ChannelDic.Remove(tChannelName);
                
throw ;
            }
      }

        
private   static  TChannel GetChannel()
        {
            TChannel instance;
            
string  tChannelName  =   typeof (TChannel).FullName;
            
if  ( ! _ChannelDic.ContainsKey(tChannelName))
            {
                
lock  (_Lockhelper)
                {
                    instance 
=  Activator.CreateInstance < TChannel > ();
                    _ChannelDic.Add(tChannelName, instance);
                }
            }
            
else
            {
                instance 
=  _ChannelDic[tChannelName];
            }
            
if  (instance.State  !=  CommunicationState.Opened  &&  instance.State  !=  CommunicationState.Opening)
                instance.Open();
            
return  instance;
        }

        
///   <summary>
        
///  直接调用,无返回值
        
///   </summary>
         public   static   void  Invoke(Action < TChannel >  action)
        {
            TChannel instance 
=  GetChannel();
            TryFunc(
                client 
=>
                {
                    action(client);
                    
return  ( object ) null ;
                }
                , instance);
        }
        
///   <summary>
        
///  有返回值的调用
        
///   </summary>
         public   static  TResult Invoke < TResult > (Func < TChannel, TResult >  func)
        {
            TChannel instance 
=  GetChannel();
            ICommunicationObject channel 
=  instance  as  ICommunicationObject;
            TResult returnValue 
=   default (TResult);
            returnValue 
=  TryFunc(func, instance);
            
return  returnValue;
        }
      }
}

 

  有了以上代码,我们就可以这样调Wcf了

 

ServiceInvokeHelper < UserClient > .Invoke(client => client.Create({ new  User{
    UserName
= " xian " ;
    Password
= " 123 " ;
}}));

 

  测试过程中发现这样不支持out 和ref参数的调用,比如这样是不可以的

 

public   void  GetUserList( int  pageindex, int  pagesize, ref  count)
{
     return  ServiceInvokeHelper < UserClient > .Invoke(client => client.GetUserList(pageindex,pagesize, ref  count));
}

 

  但是我们可以变通成如下模样

 

public   void  GetUserList( int  pageindex, int  pagesize, ref  count)
{
 int tmpCount = -1;
    var result = ServiceInvokeHelper < UserClient > .Invoke(client =>
    client.GetUserList(pageindex,pagesize, ref  tmpCount)); 
   count = tmpCount;
 return result;

}

 

  是不是方便许多,并且也不但心因为关闭不及时造成连接数到达上限的情况,看起来不起眼的一个东西就分享到这时,感谢你的阅读!

     

    参考:http://www.cnblogs.com/artech/archive/2010/01/04/1639149.html#2077613

    MSDN(忘记了:-( )

 

 

转载于:https://www.cnblogs.com/xianhong/archive/2011/04/23/2025180.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值