我无法将故障通道的概念映射回某些绑定的手动实现。我认为这个 WCF 功能很烦人,我想知道是否有任何方法可以禁用它。
以 TCP 为例。大多数 TCP 通信都断开了。那么到底为什么一个连接会导致通道故障并断开所有以下连接呢?
和命名管道?
也许我错了。所以请解释为什么它是一个特性,而不是一个错误。
我认为它是 Juval Löwy(WCF 架构师之一)WCF 整体哲学的产物。引用他的书Programming WCF Services:
这个[异常系统和正常的使用方式]是.NET作为一个平台的一个根本缺陷。[...] 这里 [在抛出异常之后],发生了一些完全出乎意料和可怕的事情。客户怎么可能假装不这样呢?该对象可能已无可救药地损坏了,但客户仍继续使用它。
这个想法是,毕竟,您正在与您正在使用的任何传输通道的另一端的对象进行通信,如果该对象抛出异常,它可能不再可用。这是一个有趣的观点,但我不确定我是否完全同意(因为,正如你所说,这在实践中可能会很烦人)。
Faulted
是CommunicationObject
状态机的状态之一,它被嵌入到许多 WCF 抽象的实现中。它本质上意味着该对象的“游戏结束”,因此您不会找到任何方法来禁用它。
这当然不是错误:CommunicationObject
所有这些人工制品背后的状态机是有意识的设计选择。虽然讨论 WCF 架构师做出的设计决策可能会引起人们的兴趣,但最终您只需要接受事情的现状并继续前进,如果您想使用 WCF。
您应该认为通道不仅仅是正在使用的传输的适配器:它是一个更高级别的抽象,它封装了通信堆栈中的许多不同层(传输、编码、安全、会话管理、事务流、双工等)。
即使查看特定绑定的详细信息,您也会发现堆栈中很少有元素具有容错性,以至于您可以在先前的通信尝试失败后安全地重用它们(例如,可能是 HTTP 协议)。即使您提到的那些(TCP,命名管道)也没有您建议的那样容错。
我认为CommunicationObject
状态机或类似的东西或多或少是必不可少的,以便拥有一个比其所有组成层/元素的细节更高级的通道抽象。它启用了简单的规则:如果是Faulted
,则将其扔掉并制作一个新的。是的,在某些情况下,您可能会错过通过保留一些可以安全重用的资源来实现的优化;但这是您为使用更简单的通信抽象而付出的(小)成本。
这就是 WCF 所做的:
Proxy a = new Proxy();
a.SomeOp() -> threw exception
a.SomeOtherOp() -> faulted
这里'SomeOp'失败了,而不是'a',那么为什么SomeOtherOp必须失败呢?
这是有道理的,如果
Proxy a = new Proxy(); -> threw exception
a.SomeOp() -> faulted