1

我使用 netNamedPipeBinding 创建了一个 WCF 单例服务。当通道异常发生时,它使通道处于故障状态,所有后续操作都会抛出异常。我怎样才能防止这种情况?我希望 TimeoutException 或任何其他常见异常仅使一个操作失败,而不是使服务无响应。

4

2 回答 2

8

您需要将服务器端的异常包装到 FaultException 中。如果您控制线路的两端,并且两端都是 .NET,则只需将 .NET 异常包装到 aFaultException<T>中并将其发送回客户端即可。这样通道就保持可用。

有关详细信息,请参阅MSDN 上的 Contracting and Services 中的指定和处理错误,以及查看CodeProject 上的这篇文章和这篇博客文章Why Use WCF FaultException on the same topic。

此外,为了让您的生活更轻松,请查看IErrorHandler 接口,您可以在服务器端实现该接口以全局捕获异常并将它们转换为故障。另请参阅有关该主题的大量博客文章,即IErrorHandler:通用故障转换器或许多其他(Bing 或 Google 更多)。

为了让您的生活更轻松,您可以将 IErrorHandler 实现为一种行为,您可以在服务上打开或关闭它 - 在服务配置中或通过设置服务类的属性。互联网上有很多实现,我喜欢的一个在这里:有用的 WCF 行为:IErrorHandler

于 2009-12-24T22:17:08.727 回答
2

还有另一种方法。您可以为每个请求实例化客户端代理,而不是为多个请求使用单个实例。这样,如果通道进入故障状态,无论如何都会被丢弃。

这有点棘手,因为除了 IDisposable 之外,您不应该处置通道。

它不起作用:

using(var channel = channelFactory.CreateChannel())
{
    return channel.ServiceMethod(parameter);
}

相反,您应该:

public static class Service<T>
{
    public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>("");

    public static TResult Use<TResult>(Func<T, TResult> func)
    {
        TResult output;
        var channel = (IClientChannel)_channelFactory.CreateChannel();
        bool success = false;
        try
        {
            output = func((T)proxy);
            channel.Close();
            success = true;
        }
        finally
        {
            if (!success)
            {
                proxy.Abort();
            }
        }
        return output;
    }
}

return Service<IService>.Use(channel =>
{
    return channel.ServiceMethod(parameter);
});
于 2010-01-04T17:34:19.897 回答