C# ChannelFactory与自动生成代理中的错误处理

C# ChannelFactory与自动生成代理中的错误处理,c#,.net,wcf,proxy,channelfactory,C#,.net,Wcf,Proxy,Channelfactory,我最近开始编写自己的ChannelFactory包装器来调用我的WCF服务,而不是依赖于VisualStudio自动生成的代码 以前,通过自动生成的代理,我可以执行以下错误检查: protected AccessControlServiceClient AccessControlService { get { // Check if not initialized yet if (HttpContex

我最近开始编写自己的ChannelFactory包装器来调用我的WCF服务,而不是依赖于VisualStudio自动生成的代码

以前,通过自动生成的代理,我可以执行以下错误检查:

    protected AccessControlServiceClient AccessControlService
    {
        get
        {
            // Check if not initialized yet
            if (HttpContext.Current.Session["AccessControlServiceClient"] == null)
                HttpContext.Current.Session["AccessControlServiceClient"] = new AccessControlServiceClient();

            // If current client is 'faulted' (due to some error), create a new instance.
            var client = HttpContext.Current.Session["AccessControlServiceClient"] as AccessControlServiceClient;
            if (client.State == CommunicationState.Faulted)
            {
                try { client.Abort(); }
                catch { /* no action */ }

                client = new AccessControlServiceClient();
                HttpContext.Current.Session["AccessControlServiceClient"] = client;
            }

            return client;
        }
    }
我应该如何处理这个问题?如果出现问题,需要处理和重新创建渠道的最佳实践是什么?e、 例如,间歇性网络连接、会话超时等

这就是我的代码当前的样子:

ProxyBase.cs中的代码段-创建通道

private void Initialise()
{
    lock (_sync)
    {
        if (_channel != null) return;

        _channel = new ChannelFactory<T>(_serviceEndPointUri).CreateChannel();
    }
 }
因此,目前,每当默认的10分钟会话启动时,我都会收到一个错误,因为通道已经关闭


如何强化代码,使其能够处理网络断开/会话超时等问题?

在我当前的项目中,我为客户端创建了一个包装类,它使用
CurrentInstance
访问器模型。getter检查
\u client.State
是否有
关闭
关闭
故障
,并在这种情况下创建新的客户端。创建新客户机是由提供给包装构造函数的工厂委托完成的,因此有一种自由但一致的方法来创建客户机实例

对于您的场景,这意味着将包装器存储在
会话中,而不是直接存储客户机。调用
wrapper.CurrentInstance
将检查状态,如果同时发生超时,将在后台重新创建客户端

该模型还可以方便地扩展为健壮的错误处理(用于物理断开连接、服务器崩溃…、延迟初始化、创建新客户端后的任意初始化逻辑(在我的例子中,它调用了某种
Subscribe
方法,创建回调通道,但它可以是任何东西)

我希望这可能也是您的正确方向。

我使用这样的代码

public T Channel {
    get {
        lock (_channelLock) {
            if (!object.Equals(_channel, default(T))) {
                if (((ICommunicationObject)_channel).State == CommunicationState.Faulted) {
                    // channel has been faulted, we want to create a new one so clear it
                    _channel = default(T);
                }
            }

            if (object.Equals(_channel, default(T))) {
                // channel is null, create a new one
                Debug.Assert(_channelFactory != null);
                _channel = _channelFactory.CreateChannel();
            }
            return _channel;
        }
   }

我通常在每个操作中使用一个新的服务实例。像这样:

public async Task<bool> IsOnline()
    {
        using (var service = new DebugService())
        {
            return await service.OnlineCheckAsync();
        }
    }

事实上,我在编辑中强调了这一点。不过,链接中可用的代码现在已在答案中。
public T Channel {
    get {
        lock (_channelLock) {
            if (!object.Equals(_channel, default(T))) {
                if (((ICommunicationObject)_channel).State == CommunicationState.Faulted) {
                    // channel has been faulted, we want to create a new one so clear it
                    _channel = default(T);
                }
            }

            if (object.Equals(_channel, default(T))) {
                // channel is null, create a new one
                Debug.Assert(_channelFactory != null);
                _channel = _channelFactory.CreateChannel();
            }
            return _channel;
        }
   }
public async Task<bool> IsOnline()
    {
        using (var service = new DebugService())
        {
            return await service.OnlineCheckAsync();
        }
    }
public void Dispose()
    {
        // The following code is from: http://www.vasylevskyi.com/2010/11/correct-wcf-client-proxy-closing.html
        try
        {
            if (this.State != CommunicationState.Closed && this.State != CommunicationState.Faulted)
            {
                ((ICommunicationObject)this).BeginClose(
                    (asr) =>
                    {
                        try
                        {
                            ((ICommunicationObject)this).EndClose(asr);
                        }
                        catch
                        {
                            this.Abort();
                        }
                    }, null
                );
            }
            else
            {
                this.Abort();
            }
        }
        catch (CommunicationException)
        {
            this.Abort();
        }