“使用”语句中的exception,WCF没有正确关闭连接。 如何关闭故障WCF客户端连接或具有exception的连接?

关于关闭WCF连接的StackOverflow有几个问题,但排名最高的答案是指这个博客:

http://marcgravell.blogspot.com/2008/11/dontdontuse-using.html

当我在服务器上设置断点并让客户端挂起超过一分钟时,我遇到了这种技术的问题。 (我故意创建超时exception)

问题是客户端似乎“挂起”,直到服务器完成处理。 我的猜测是,一切都在exception后被清理干净。

关于TimeOutException ,似乎客户端的retry()逻辑将继续一遍又一遍地重新提交查询到服务器,在那里我可以看到服务器端调试器对请求进行排队,然后同时执行每个排队请求 。 我的代码不希望WCF这样做,可能是我看到的数据损坏问题的原因。

有些东西并没有完全加入这个解决方案。

什么是在WCF代理中处理故障和exception的无所不包的现代方法?

更新

不可否认,这是一些平凡的代码。 我目前更喜欢这个链接的答案 ,并且在该代码中看不到任何可能导致问题的“黑客”。


这是Microsoft推荐的处理WCF客户端调用的方法:

有关更多详细信息,请参阅: 预期的例外情况

 try { ... double result = client.Add(value1, value2); ... client.Close(); } catch (TimeoutException exception) { Console.WriteLine("Got {0}", exception.GetType()); client.Abort(); } catch (CommunicationException exception) { Console.WriteLine("Got {0}", exception.GetType()); client.Abort(); } 

其他信息很多人似乎在WCF上问这个问题,微软甚至创建了一个专门的示例来演示如何处理exception:

C:\ WF_WCF_Samples \ WCF \基本\客户端\ ExpectedExceptions \ CS \客户端

下载示例: C#或VB

考虑到涉及使用声明的问题很多, (加热吗?)关于这个问题的内部讨论和线程 ,我不会浪费我的时间试图成为代码牛仔并找到一种更清洁的方式。 我只是搞砸了,并为我的服务器应用程序实现了这种冗长(但可靠)的WCF客户端。

可选的附加故障

许多exception派生自CommunicationException ,我认为大多数exception都不应该重试。 我在MSDN上浏览了每个exception,并找到了一个可重试exception的简短列表(除了上面的TimeOutException之外)。 如果我错过了应该重试的exception,请告诉我。

 Exception mostRecentEx = null; for(int i=0; i<5; i++) // Attempt a maximum of 5 times { try { ... double result = client.Add(value1, value2); ... client.Close(); } // The following is typically thrown on the client when a channel is terminated due to the server closing the connection. catch (ChannelTerminatedException cte) { mostRecentEx = cte; secureSecretService.Abort(); // delay (backoff) and retry Thread.Sleep(1000 * (i + 1)); } // The following is thrown when a remote endpoint could not be found or reached. The endpoint may not be found or // reachable because the remote endpoint is down, the remote endpoint is unreachable, or because the remote network is unreachable. catch (EndpointNotFoundException enfe) { mostRecentEx = enfe; secureSecretService.Abort(); // delay (backoff) and retry Thread.Sleep(1000 * (i + 1)); } // The following exception that is thrown when a server is too busy to accept a message. catch (ServerTooBusyException stbe) { mostRecentEx = stbe; secureSecretService.Abort(); // delay (backoff) and retry Thread.Sleep(1000 * (i + 1)); } catch(Exception ex) { throw ex; // rethrow any other exception not defined here } } if (mostRecentEx != null) { throw new Exception("WCF call failed after 5 retries.", mostRecentEx ); } 

关闭和处置WCF服务

正如该帖所暗示的那样,当没有exception时你关闭,当你有错误时你就中止。 Dispose和因此Using不应与WCF一起使用。