WCF使用,关闭和扩展

时间:2013-05-08 14:09:03

标签: c# wcf

我很难过。也许有人可以对我观察到的WCF客户端行为有所了解。

使用WCF示例,我开始使用不同的WCF客户端/服务器通信方法。在并行执行1M测试请求时,我使用SysInternals TcpView来监视开放端口。现在,至少有4种不同的方式来调用客户端:

  1. 创建客户端,做你自己的事情,让GC收集它
  2. 使用块创建客户端,而不是使用
  3. 使用块创建工厂中的客户端通道,而不是使用
  4. 创建客户端或频道,但使用WCF Extensions来做您的事情
  5. 现在,据我所知,只有选项2-4,显式调用client.Close()。在执行期间,我看到许多端口处于TIME_WAIT状态。由于依赖GC,我期望选项1成为最糟糕的情况。然而,令我惊讶的是,它似乎是最干净的,这意味着它不会留下任何挥之不去的端口。

    我错过了什么?

    更新:源代码

        private static void RunClientWorse(ConcurrentBag<double> cb)
        {
            var client = new CalculatorClient();
            client.Endpoint.Address = new EndpointAddress("net.tcp://localhost:8000/ServiceModelSamples/service");
            RunClientCommon(cb, client);                        
        }
    
        private static void RunClientBetter(ConcurrentBag<double> cb)
        {
            using (var client = new CalculatorClient())
            {
                client.Endpoint.Address = new EndpointAddress("net.tcp://localhost:8000/ServiceModelSamples/service");
                RunClientCommon(cb, client);
            }
        }
    
        private static void RunClientBest(ConcurrentBag<double> cb)
        {
            const string Uri = "net.tcp://localhost:8000/ServiceModelSamples/service";
            var address = new EndpointAddress(Uri);
            //var binding = new NetTcpBinding("netTcpBinding_ICalculator");
            using (var factory = new ChannelFactory<ICalculator>("netTcpBinding_ICalculator",address))
            {
                ICalculator client = factory.CreateChannel();
                ((IContextChannel)client).OperationTimeout = TimeSpan.FromSeconds(60);
                RunClientCommon(cb, client);
            }
        }
    
        private static void RunClientBestExt(ConcurrentBag<double> cb)
        {
            const string Uri = "net.tcp://localhost:8000/ServiceModelSamples/service";
            var address = new EndpointAddress(Uri);
            //var binding = new NetTcpBinding("netTcpBinding_ICalculator");
            new ChannelFactory<ICalculator>("netTcpBinding_ICalculator", address).Using(
                factory =>
                    {
                        ICalculator client = factory.CreateChannel();
                        ((IContextChannel)client).OperationTimeout = TimeSpan.FromSeconds(60);
                        RunClientCommon(cb, client);
                    });
        }
    

1 个答案:

答案 0 :(得分:1)

我认为,我已经弄明白了。 GC不会在ClientBase上调用Dispose。这就是连接没有处于TIME_WAIT状态的原因。所以我决定遵循相同的模式并创建一个新的WCF扩展:

    public static void UsingAbort<T>(this T client, Action<T> work)
        where T : ICommunicationObject
    {
        try
        {
            work(client);
            client.Abort();
        }
        catch (CommunicationException e)
        {
            Logger.Warn(e);
            client.Abort();
        }
        catch (TimeoutException e)
        {
            Logger.Warn(e);
            client.Abort();
        }
        catch (Exception e)
        {
            Logger.Warn(e);
            client.Abort();
            throw;
        }
    }
}

这样,在请求结束时,它将简单地中止连接而不是关闭它。