zoukankan      html  css  js  c++  java
  • 明确的说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(忘记了:-( )

  • 相关阅读:
    Writing Custom Providers
    terraform 几个方便的工具
    几张简单的terraform flow 图——可以快速了解terraform的使用
    Stateful Kubernetes Applications Made Easier: PSO and FlashBlade
    使用k8s && minio 进行 postgres 数据库自动备份
    Understanding how uid and gid work in Docker containers
    nightwatchjs 基于nodejs&& webdriver 协议的自动化测试&&持续集成框架
    hasura graphql-engine graphql2chartjs 方便的graphql 转换chartjs 的类库
    nginx unit 1.8 支持基于java servlet 的开发模型
    试用 openresty/lua-resty-shell
  • 原文地址:https://www.cnblogs.com/xianhong/p/2025180.html
Copyright © 2011-2022 走看看