WCF代理客户端花时间为它创建任何缓存或单例解决方案

Tec*_*ter 7 wcf wcf-client

我们有更多的wcf服务,并使用TCP绑定进行调用.在代码的不同位置有很多调用相同的wcf服务.

AdminServiceClient client = FactoryS.AdminServiceClient(); //需要很长时间.和

client.GetSomeThing(参数1); client.Close();

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

谢谢

Fra*_*sca 8

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

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

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

proxyInstance.InnerChannel.Faulted += new EventHandler(ProxyFaulted);
Run Code Online (Sandbox Code Playgroud)

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

编辑:如果您不想一直打开代理通道,则必须在每次使用之前测试通道的状态,并在出现故障时重新创建代理.一旦频道出现故障,除了创建一个新频道之外别无选择.

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

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

这是一个简单的单例类,它应该包含你需要的东西:

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;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望有帮助:)