当前位置: 首页 > news >正文

在客户端正确的关闭WCF连接! zt

在客户端正确的关闭WCF连接!

如果你直接将客户端调用Close关闭,或者使用using语句,那你将是个悲剧,这点相信使用WCF的同志都知道的,因为ClientBase类的Close()方法被调用后,实际上是关闭了一个网络会话,并且会抛出异常!CommunicationException和TimeoutException!

这似乎违反常理,但确实发生了。因为一般来说Close函数都不会抛出异常。这个问题的解决办法是使用Try-Catch语句包含Close()方法,然后再异常处理中使用Abort函数释放资源!

同样,ClientBase类的IDisposable接口的实现函数Dispose方法中会调用Close函数,使用Reflector查看ClientBase<TChannel> 的代码便知

所以你使用using语句同样不能正确关闭WCF连接!而我们使用using语句就是为了不管发生什么情况,只要离开作用域之后,就会释放相关资源。而WCF的ClientBase类设计很明显违反了这一观念!简直是坑爹啊!

解决这一问题网上以后很多方案,首先说说微软的,也许是微软也意识到这一点,所以微软在提供的WCF示例程序中特意包含了一个叫做UsingUsing的示例,名字听起来有点怪

主要解决的方法是如下的代码

复制代码
 1 // This method shows the correct way to clean up a client, including catching the
 2         // approprate Exceptions.
 3         static void DemonstrateCleanupWithExceptions()
 4         {
 5             // Create a client
 6             CalculatorClient client = new CalculatorClient();
 7             try
 8             {
 9                 // Demonstrate a successful client call.
10                 Console.WriteLine("Calling client.Add(0.0, 0.0);");
11                 double addValue = client.Add(0.0, 0.0);
12                 Console.WriteLine("        client.Add(0.0, 0.0); returned {0}", addValue);
13 
14                 // Demonstrate a failed client call.
15                 Console.WriteLine("Calling client.Divide(0.0, 0.0);");
16                 double divideValue = client.Divide(0.0, 0.0);
17                 Console.WriteLine("        client.Divide(0.0, 0.0); returned {0}", divideValue);
18 
19                 // Do a clean shutdown if everything works.  In this sample we do not end up
20                 // here, but correct code should Close the client if everything was successful.
21                 Console.WriteLine("Closing the client");
22                 client.Close();
23             }
24             catch (CommunicationException e)
25             {
26                 // Because the server suffered an internal server error, it rudely terminated
27                 // our connection, so we get a CommunicationException.
28                 Console.WriteLine("Got {0} from Divide.", e.GetType());
29                 client.Abort();
30             }
31             catch (TimeoutException e)
32             {
33                 // In this sample we do not end up here, but correct code should catch
34                 // TimeoutException when calling a client.
35                 Console.WriteLine("Got {0} from Divide.", e.GetType());
36                 client.Abort();
37             }
38             catch (Exception e)
39             {
40                 // In this sample we do not end up here.  It is best practice to clean up the
41                 // client if some unexpected Exception occurs.
42                 Console.WriteLine("Got unexpected {0} from Divide, rethrowing.", e.GetType());
43                 client.Abort();
44                 throw;
45             }
46         }
复制代码

其实就是使用try-catch语句捕获关闭时的异常!试想要是每次都这样调用WCF服务将会是多么痛苦的一件事情!网上也有人使用Linq的Expression来解决这一问题

于是我借用函数式编程的思想,设计了一个使用lambda表达式来解决这一问题的方案!

关键的函数很简单,一看便知道是我是怎样设计的!

复制代码
 1 public static class SvcClient
 2     {
 3         public static void Invoke<TClient>(Action<TClient> act)
 4             where TClient : System.ServiceModel.ICommunicationObject, new()
 5         {
 6             TClient client = new TClient();
 7             try
 8             {
 9                 act(client);
10                 client.Close();
11             }
12             catch (System.ServiceModel.CommunicationException)
13             {
14                 client.Abort();
15             }
16             catch (TimeoutException)
17             {
18                 client.Abort();
19             }
20             catch (Exception)
21             {
22                 client.Abort();
23                 throw;
24             }
25         }
26     }
复制代码

实际上这一设计的思想就是:将所有调用WCF服务的所有代码做为一个函数传入进来,然后我再内部使用try-catch语句包裹整个调用过程,这样就巧妙的将处理关闭连接异常的代码与实际调用过程分离开来!

函数的使用过程也比较方便

1 SvcClient.Invoke<Service1Client>(client =>
2 {
3   //在此处添加调用WCF的代码
4 });

代码看起来比较简洁优美,个人比较满意,而且不用再担心调用结束后不能正确关闭WCF连接,资源不能正确释放的问题了!

相关文章:

  • 公司ERP服务器中勒索病毒原因事后分析
  • 关于I/O上下拉电阻的应用总结
  • babylonjs
  • 列表的基本操作元组
  • Mysql GRANT 添加用户
  • RocksDB介绍
  • poj 2777 Count Color(线段树区间更新)
  • 基础正则表达式
  • binlog2sql 回滚误操作
  • Dynamic Properties in PHP and StdClass
  • NoSQL实现(1)——Redis
  • MySQL学习四部曲
  • vim常用命令总结 (转)【转】
  • 深入理解dp px density
  • java基础---一致性hash算法
  • 2019.2.20 c++ 知识梳理
  • Github访问慢解决办法
  • HTML5新特性总结
  • Mac转Windows的拯救指南
  • mongo索引构建
  • oschina
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • 当SetTimeout遇到了字符串
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 想写好前端,先练好内功
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (0)Nginx 功能特性
  • (1)SpringCloud 整合Python
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (转) Face-Resources
  • ***利用Ms05002溢出找“肉鸡
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .NET gRPC 和RESTful简单对比
  • @Autowired @Resource @Qualifier的区别
  • @cacheable 是否缓存成功_Spring Cache缓存注解
  • [Angularjs]asp.net mvc+angularjs+web api单页应用之CRUD操作
  • [ANT] 项目中应用ANT
  • [CLR via C#]11. 事件
  • [Codeforces] number theory (R1600) Part.11
  • [EFI]Atermiter X99 Turbo D4 E5-2630v3电脑 Hackintosh 黑苹果efi引导文件
  • [error] 17755#0: *58522 readv() failed (104: Connection reset by peer) while reading upstream
  • [FUNC]判断窗口在哪一个屏幕上
  • [hibernate]基本值类型映射之日期类型
  • [IE编程] 如何设置IE8的WebBrowser控件(MSHTML) 的渲染模式
  • [oeasy]python0004_游乐场_和python一起玩耍_python解释器_数学运算
  • [POI2006] OKR-Periods of Words——最大周期长度(扩展最小周期长度)
  • [SWPUCTF 2021 新生赛]easy_md5
  • [WinForm]DataGridView通过代码新增行问题
  • [大厂实践] Netflix容器平台内核panic可观察性实践
  • [导入]SQL Server练习题2
  • [豆趣]成长日记