WCF代理运行时初始化和性能影响

WCF代理运行时初始化和性能影响,wcf,wcf-client,Wcf,Wcf Client,我正在通过ChannelFactory类手动初始化我的代理,因为初始化此代理的配置来自其他一些配置服务(不在同一App.Config中),并且为了避免初始化成本(服务调用、读取配置设置),我缓存了此代理。我无法承担每次操作后关闭此代理的成本,因为需要频繁执行操作。此代理的超时配置如下所示 receiveTimeout="00:10:00" sendTimeout="00:10:00" closeTimeout="00:10:00" 根据我对客户端超时属性的理解,当超时超过时,我的代理的状态

我正在通过ChannelFactory类手动初始化我的代理,因为初始化此代理的配置来自其他一些配置服务(不在同一App.Config中),并且为了避免初始化成本(服务调用、读取配置设置),我缓存了此代理。我无法承担每次操作后关闭此代理的成本,因为需要频繁执行操作。此代理的超时配置如下所示

receiveTimeout="00:10:00" 
sendTimeout="00:10:00" 
closeTimeout="00:10:00"
根据我对客户端超时属性的理解,当超时超过时,我的代理的状态将为Fault。对吧?

我想重新初始化我的代理,所以我有2个选项来执行此操作

1) 我使用ICommunicationObject.Faulted事件处理程序,在这种情况下,当我的代理移动到故障状态时,我甚至会重新初始化代理。但是这个实现并不合适,因为我们没有正确地处理代理(调用.Close()方法),而且它不会从服务端释放资源,也不会影响我的性能

2) 我创建了一个线程,并在代理进入故障状态前几秒钟设置它的运行时间。通过调用.Close{)方法正确关闭此代理,然后重新初始化另一个对象并缓存它

请建议我哪一个选项在性能方面是好的,并告诉我是否存在其他解决方案来避免此问题


提前感谢。

如果代理处于故障状态,您可以对其调用Abort。 如果您真的想保留代理,这取决于您需要什么。如果您打算使用双工通信或类似的方式,这可能是一个很好的建议。如果您只是偶尔调用服务,您可以只在调用期间使用代理

我通常会为自己编写一个小代理,只发布连接和故障事件。我使用代码实现IDisposable,该代码首先尝试关闭代理,然后在抛出CommunicationException时终止它

在处理通信的代码中,我持有对这样一个代理对象的引用,并在Close/Fault上处理它,一旦有操作挂起就打开它。 即使在网络不可靠的情况下,这在客户端也能很好地工作。 在双工服务的情况下,我只是添加了一个计时器,如果连接丢失,它会尝试自动重新连接

这里是F#中的一个小片段,演示了我使用这个非常简单的代理的方式-它实际上只不过是包装通道和获取连接事件-WcfHelper只是一组用于建立地址和绑定的帮助函数-这个案例是DuplexService的精简版本,因此它继承自DuplexClientBase b但是,正常的非双工情况是一样的

/// Duplex-proxy
type private MyProxy(handler, servicename: string, server : string, port : int) =
    inherit DuplexClientBase<IWcfConnector>(handler, WcfHelper.getBinding(), WcfHelper.createEndpointAddress(servicename, server, port))

    let _connectionEvent = new Event<_>()

    do
        base.InnerDuplexChannel.Closed.Add(fun _ -> _connectionEvent.Trigger(ConnectionState.Disconnected))
        base.InnerDuplexChannel.Opened.Add(fun _ -> _connectionEvent.Trigger(ConnectionState.Connected))
        base.InnerDuplexChannel.Faulted.Add(fun _ -> _connectionEvent.Trigger(ConnectionState.Disconnected))

    /// sample-Operation
    member i.TestCall(message) = base.Channel.TestCall(message)

    interface IDisposable with
        member i.Dispose() =
            try
                i.Close()
            with
            | :? CommunicationException ->
                i.Abort()
///双工代理
键入private-MyProxy(处理程序,servicename:string,服务器:string,端口:int)=
继承DuplexClientBase(处理程序,WcfHelper.getBinding(),WcfHelper.createEndpointAddress(servicename,服务器,端口))
let _connectionEvent=新事件()
做
base.InnerDuplexChannel.Closed.Add(fun->\u connectionEvent.Trigger(ConnectionState.Disconnected))
base.InnerDuplexChannel.Opened.Add(fun->connectionEvent.Trigger(ConnectionState.Connected))
base.InnerDuplexChannel.Faulted.Add(fun->\u connectionEvent.Trigger(ConnectionState.Disconnected))
///样本操作
成员i.TestCall(消息)=base.Channel.TestCall(消息)
接口IDisposable与
委员一()=
尝试
i、 关闭()
具有
|:?通信异常->
i、 中止

调用Abort()只会从客户端释放资源。调用Close()时也从服务端释放资源。例如,如果我设置MaxConcurrentInstances=1和InstanceContextMode=PerCall,这意味着一个代理实例一次可以服务/连接该服务。如果我持有该代理实例,它进入故障状态,然后调用Abort()怎么办并尝试重新初始化它,因为服务端的另一个实例未正常关闭,所以任何一个服务都将允许/招待该代理实例?如果代理处于故障状态,您对此无能为力。如果您的网络连接丢失怎么办?没有IMHO MaxConcurrentInstances(在PerCall场景中)只告诉服务器一次可以实例化多少个服务对象-如果这是一个调用,而另一个调用到来,则调用只需等到实例一完成。你是对的MaxConcurrentInstances只告诉服务器它可以实例化多少个服务对象。如果我错了,请纠正我,代理启动通信h服务但未调用/invoke Close()方法我假设服务不会同时处理InstanceContext(和相关资源),如果另一个调用到达,它将保持等待状态,直到proxy1调用Close()为止方法。这可能取决于proxy/call/INstanceContextMode的类型,我必须阅读文档或进行测试才能确定,但我认为服务器对关闭客户端一点也不感兴趣。这种情况下(每次调用)与ASP.NET几乎相同-服务对象在调用时创建,成员被调用,仅此而已。OK Carsten我也尝试过测试此场景,并将与您共享。请共享您为发布连接事件和故障事件而编写的代理的代码,并使用首先尝试关闭prox的代码实现IDisposable当抛出一个CommunicationException时,它会继续中止你在回复中提到的,或者引用任何文章或知识库。这对我来说一定是有益的。