如何防止通道异常导致WCF服务停止工作?

发布于 2024-08-15 13:19:49 字数 143 浏览 6 评论 0 原文

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

I created a WCF singleton service with netNamedPipeBinding. When a channel exception occurs, it leaves a channel in a faulty state, and all subsequent operations throws exceptions. How can I prevent this? I want that a TimeoutException, or any of the other common exceptions, to make only one operation fail, and not to make the service unresponsive.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你是我的挚爱i 2024-08-22 13:19:49

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

有关详细信息,请参阅 MSDN 上的指定和处理合同和服务中的故障 ,另请查看这篇关于 CodeProject 的文章和这篇博文为什么在同一主题上使用 WCF FaultException

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

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

You need to wrap your exceptions on the server side into FaultException. If you control both ends of the wire, and both ends are .NET, you can just simply wrap a .NET exception into a FaultException<T> and send that back to the client. That way the channel stays usable.

See Specifying and Handling Faults in Contracts and Services on MSDN for more info, plus check out this article on CodeProject and this blog post Why Use WCF FaultException on the same topic.

Also, to make your life easier, check out the IErrorHandler interface which you can implement on the server side to globally catch exceptions and convert them into faults. Also see lots of blog posts on the topic, i.e. IErrorHandler: a generic Fault Converter or many other (Bing or Google for more).

To make your life even easier, you can implement the IErrorHandler as a behavior, which you can turn on or off on your service - either in service config, or by setting an attribute on your service class. There's quite a few implementation floating around the internet, one I like is here: Useful WCF Behavior: IErrorHandler.

你穿错了嫁妆 2024-08-22 13:19:49

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

这有点棘手,因为除了 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);
});

There is another way. You can instantiate the client proxy for each request instead of using a single instance for more than one request. This way if the channel enters a faulty state, it is discarded anyway.

This is a bit tricky because you shouldn't dispose a channel, besides it being IDisposable.

It won't work:

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

Instead you should:

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);
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文