本文介绍了WCF 代理客户端花时间为其创建任何缓存或单例解决方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有超过 dozon 的 wcf 服务并且使用 TCP 绑定被调用.在代码的不同地方有很多对相同 wcf 服务的调用.

we have more than dozon of wcf services and being called using TCP binding. There are a lots of calls to same wcf service at various places in code.

AdminServiceClient client = FactoryS.AdminServiceClient();// it takes significant time. and 

client.GetSomeThing(param1);
client.Close();

我想缓存客户端或从单例中生成它.这样我可以节省一些时间,可以吗?

i want to cache the client or produce it from singleton. so that i can save some time, Is it possible?

谢谢

推荐答案

是的,这是可能的.您可以使代理对象对整个应用程序可见,或者将其包装在一个单例类中以保持整洁(我的首选选项).但是,如果您要为服务重用代理,则必须处理通道故障.

Yes, this is possible. You can make the proxy object visible to the entire application, or wrap it in a singleton class for neatness (my preferred option). However, if you are going to reuse a proxy for a service, you will have to handle channel faults.

首先创建您的单例类/缓存/全局变量,其中包含要重用的代理(或多个代理)实例.

First create your singleton class / cache / global variable that holds an instance of the proxy (or proxies) that you want to reuse.

创建代理时,需要在内部通道订阅Faulted事件

When you create the proxy, you need to subscribe to the Faulted event on the inner channel

proxyInstance.InnerChannel.Faulted += new EventHandler(ProxyFaulted);

然后将一些重新连接代码放入 ProxyFaulted 事件处理程序中.如果服务中断或连接因空闲而超时,则将触发 Faulted 事件.仅当您在配置文件中的绑定上启用了可靠会话时,才会触发故障事件(如果未指定,则默认为在 netTcpBinding 上启用).

and then put some reconnect code inside the ProxyFaulted event handler. The Faulted event will fire if the service drops, or the connection times out because it was idle. The faulted event will only fire if you have reliableSession enabled on your binding in the config file (if unspecified this defaults to enabled on the netTcpBinding).

如果你不想让你的代理频道一直打开,你必须在每次使用之前测试频道的状态,如果出现故障,则重新创建代理.一旦通道出现故障,就别无选择,只能创建一个新通道.

If you don't want to keep your proxy channel open all the time, you will have to test the state of the channel before every time you use it, and recreate the proxy if it is faulted. Once the channel has faulted there is no option but to create a new one.

Edit2:保持通道打开和每次关闭它之间唯一真正的负载区别是一个保持活动的数据包被发送到服务并经常被确认(这是你的通道故障事件背后的原因).有 100 个用户,我认为这不会成为问题.

The only real difference in load between keeping the channel open and closing it every time is a keep-alive packet being sent to the service and acknowledged every so often (which is what is behind your channel fault event). With 100 users I don't think this will be a problem.

另一种选择是将您的代理创建放在 using 块中,它将在块的末尾关闭/处理(即 被认为是不好的做法).调用后关闭通道可能会导致您的应用程序挂起,因为服务尚未完成处理.事实上,即使您对服务的调用是异步的,或者该方法的服务契约是单向的,通道关闭代码也会阻塞,直到服务完成.

The other option is to put your proxy creation inside a using block where it will be closed / disposed at the end of the block (which is considered bad practice). Closing the channel after a call may result in your application hanging because the service is not yet finished processing. In fact, even if your call to the service was async or the service contract for the method was one-way, the channel close code will block until the service is finished.

这是一个简单的单例类,它应该包含您所需要的基本内容:

Here is a simple singleton class that should have the bare bones of what you need:

public static class SingletonProxy
{
    private CupidClientServiceClient proxyInstance = null;
    public CupidClientServiceClient ProxyInstance
    {
        get
        {
            if (proxyInstance == null)
            {
                AttemptToConnect();
            }
            return this.proxyInstance;
        }
    }

    private void ProxyChannelFaulted(object sender, EventArgs e)
    {
        bool connected = false;
        while (!connected)
        {
            // you may want to put timer code around this, or 
            // other code to limit the number of retrys if 
            // the connection keeps failing
            AttemptToConnect();
        }
    }

    public bool AttemptToConnect()
    {
        // this whole process needs to be thread safe
        lock (proxyInstance)
        {
            try
            {
                if (proxyInstance != null)
                {
                    // deregister the event handler from the old instance
                    proxyInstance.InnerChannel.Faulted -= new EventHandler(ProxyChannelFaulted);
                }

                //(re)create the instance
                proxyInstance = new CupidClientServiceClient();
                // always open the connection
                proxyInstance.Open();

                // add the event handler for the new instance
                // the client faulted is needed to be inserted here (after the open)
                // because we don't want the service instance to keep faulting (throwing faulted event)
                // as soon as the open function call.
                proxyInstance.InnerChannel.Faulted += new EventHandler(ProxyChannelFaulted);

                return true;
            }
            catch (EndpointNotFoundException)
            {
                // do something here (log, show user message etc.)
                return false;
            }
            catch (TimeoutException)
            {
                // do something here (log, show user message etc.)
                return false;
            }
        }
    }
}

我希望有帮助:)

这篇关于WCF 代理客户端花时间为其创建任何缓存或单例解决方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 13:18