我们有一个从 Web 应用程序使用的 WCF 服务。我们使用的客户端是使用 Visual Studio 的“添加服务引用”选项生成的。由于它是一个网络应用程序,并且由于该应用程序的性质可能会导致相对较短的 session ,我们选择在用户登录时创建一个客户端实例并在 session 的整个生命周期内保留它,然后在 session 结束时处理它。
这让我想到了我的问题 - 我们正在尝试确定处理客户端 channel 进入故障状态的最佳方式。在搜索了一些之后,我们想出了这个:
if(client.State = CommuncationState.Faulted)
{
client = new Client();
}
try
{
client.SomeMethod();
}
catch //specific exceptions left out for brevity
{
//logging or whatever we decide to do
throw;
}
然而,这不起作用,因为至少在我们的例子中,即使服务已关闭,客户端也会显示 Open
状态,直到您真正尝试调用电话使用它,此时它进入 Faulted
状态。
所以这让我们去做其他事情。我们想到的另一个选择是:
try
{
client.SomeMethod();
}
catch
{
if(client.State == CommunicationState.Faulted)
{
//we know we're faulted, try it again
client = new Client();
try
{
client.SomeMethod();
}
catch
{
throw;
}
}
//handle other exceptions
}
但是那味道。显然,我们可以通过使用新客户端并在每次调用时处理掉它来避免这种情况。这似乎没有必要,但如果这是正确的方式,那么我想这就是我们会选择的方式。那么,优雅地处理确定客户端是否处于故障状态然后采取措施的最佳方式是什么?我们真的应该为每个电话都获得一个新客户吗?
还有一件事要记住——客户端的实例化以及所有这些检查和处理都发生在客户端的包装类中。如果我们按照预期的方式执行此操作,它对应用程序本身是透明的 - 进行调用和处理它们的异常不需要那里的特殊代码。
最佳答案
要回答您的问题,您可以处理 Faulted event像这样的 ChannelFactory 属性:
client.ChannelFactory.Faulted += new EventHandler(ChannelFactory_Faulted);
这应该允许您执行您需要执行的任何日志记录/清理操作。
作为一般性建议,您不应在 session 期间让 channel 保持打开状态,因此请确保在完成后正确关闭 channel (异常中止)。
此外,如果可能,请考虑不使用 Visual Studio 添加服务引用,或者至少清理它生成的代码/配置。我建议如果你想使用代理实现,通过从 ClientBase 派生来创建你自己的,或使用 ChannelFactory执行。由于您提到了包装类,我建议您使用 ChannelFactory 并处理 Faulted event满足您的清理需求。
关于c# - 处理进入故障状态的持久性 WCF 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5464195/