西西软件园多重安全检测下载网站、值得信赖的软件下载站!
软件
软件
文章
搜索

首页编程开发其它知识 → WCF编程中需要及时关闭的案例分享

WCF编程中需要及时关闭的案例分享

相关软件相关文章发表评论 来源:西西整理时间:2011/4/24 7:57:26字体大小:A-A+

作者:西西点击:293评论:2次标签: WCF

手机QQ2017 for Androidv6.6.9 官方最新版
  • 类型:社交聊天大小:37.8M语言:中文 评分:8.0
  • 标签:寂寞交友生活分享2015最受欢迎APP00后最常用的appqq2016
立即下载

刚学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)
{
    return ServiceInvokeHelper<UserClient>.Invoke(client=>

   {

    int tmpCount = -1;

    client.GetUserList(pageindex,pagesize,ref tmpCount));

    count = tmpCount;

  }
}

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

  • 寂寞交友
  • 生活分享
  • 2015最受欢迎APP
  • 00后最常用的app
  • qq2016
寂寞交友
(73)寂寞交友
寂寞交友由西西为大家整理一系列火热的社交应用,因为寂寞而交友,随着时代的发展,人们越来越无法满足现有的交际圈子,对于择偶标准的提高,催生出一系列单身男女的情感问题,压抑的情绪需要得到一定的释放,如果你想找寻属于自己的缘分,就赶快下载吧。交友软件排行微信企鹅之子的基数之巨大,寂寞的时候摇一摇,丝男也会有春天不过企鹅之子也有个弊病,依托于的用户资源,环肥燕瘦难以保证。来往来往是拼爹的,背靠大树好乘凉。...更多>>

相关评论

阅读本文后您有什么感想? 已有人给出评价!

  • 1 喜欢喜欢
  • 1 顶
  • 1 难过难过
  • 27 囧
  • 0 围观围观
  • 1 无聊无聊

热门评论

最新评论

发表评论 查看所有评论(2)

昵称:
表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲
字数: 0/500 (您的评论需要经过审核才能显示)

WCF编程中需要及时关闭的案例分享

手机QQ2017 for Android标签:寂寞交友生活分享2015最受欢迎APP00后最常用的appqq2016

手机QQ2017 for Android