代码之家  ›  专栏  ›  技术社区  ›  gsharp

关闭ServiceClient状态的模式

  •  1
  • gsharp  · 技术社区  · 17 年前

    我希望确保WCF ServiceClient状态在使用该服务后关闭。

    我实施了以下代码以确保:

    public static class ServiceClientFactory
    {
        public static ServiceClientHost<T> CreateInstance<T>() where T : class, ICommunicationObject, new()
        {
            return new ServiceClientHost<T>();
        }
    }
    
    public class ServiceClientHost<T> : IDisposable where T : class, ICommunicationObject, new()
    {
        private bool disposed;
    
        public ServiceClientHost()
        {
            Client = new T();
        }
    
        ~ServiceClientHost()
        {
            Dispose(false);
        }
    
        public T Client { get; private set; }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        protected virtual void Dispose(bool disposeManagedResources)
        {
            if(!disposed)
            {
                if(disposeManagedResources)
                {
                    Client.Close();
                    Client = null;
                }
                disposed = true;
            }
        }
    }
    

    用法:

    using (var host = ServiceClientFactory.CreateInstance<MySericeClient>())
    {
       host.Client.DoSomething();
    }
    

    我想知道是否有比我的更好/更优雅的解决方案?

    1 回复  |  直到 14 年前
        1
  •  2
  •   marc_s MisterSmith    17 年前

    对于一次性对象,使用using块通常是一个好主意,但对于WCF代理则不是这样。问题在于,当关闭代理(在使用块的末尾)时,很有可能发生异常,然后该异常将不被处理(可能),并且代理未真正关闭。

    建议的最佳做法是:

    try
    {
       var host = ServiceClientFactory.CreateInstance<MySericeClient>();
    
       ...... (use it).......
    
       host.Close();
    }
    catch(FaultException)
    {   
       host.Abort();
    }
    catch(CommunicationException)
    {
       host.Abort();
    }
    

    问题是-如果在通信过程中出现任何错误,您的通道将处于“故障”状态,并且在该通道上调用.Close()”将导致异常。

    因此,捕获故障异常(来自服务器的信号出错)和通信异常(故障和其他WCF客户端异常的基类),在这种情况下,使用proxy.Abort()强制中止/关闭代理(不是优雅地等待操作完成,而只是掷重锤)。

    马克