Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从另一个WCF服务内调用WCF服务时WCF内存泄漏_C#_.net_Wcf_Memory Leaks - Fatal编程技术网

C# 从另一个WCF服务内调用WCF服务时WCF内存泄漏

C# 从另一个WCF服务内调用WCF服务时WCF内存泄漏,c#,.net,wcf,memory-leaks,C#,.net,Wcf,Memory Leaks,我注意到WCF应用程序中存在内存泄漏问题,并设法在一个简单的程序中复制它。当从另一个WCF服务中调用WCF服务时,会发生此问题 在下面的示例中,我有两个服务A和B。当我调用服务A上的DoWork方法时,它反过来调用服务B的DoWork方法 在下面的示例中,我每次都创建一个新的ChannelFactory,使用它打开一个频道,调用DoWork,然后在最后处理频道和工厂。这样,进程开始泄漏内存 如果每次(注释并取消注释示例中的标记行)都将其中一个调用或两个调用设置为重用相同的ChannelFacto

我注意到WCF应用程序中存在内存泄漏问题,并设法在一个简单的程序中复制它。当从另一个WCF服务中调用WCF服务时,会发生此问题

在下面的示例中,我有两个服务
A
B
。当我调用服务
A
上的
DoWork
方法时,它反过来调用服务
B
DoWork
方法

在下面的示例中,我每次都创建一个新的
ChannelFactory
,使用它打开一个频道,调用
DoWork
,然后在最后处理频道和工厂。这样,进程开始泄漏内存

如果每次(注释并取消注释示例中的标记行)都将其中一个调用或两个调用设置为重用相同的
ChannelFactory
,则泄漏停止

如果每次调用service
a
时都不断创建一个新的
ChannelFactory
,但将
ServiceA
的DoWork方法清空(这样它就不会调用
ServiceB
),则不会发生泄漏

我正在运行针对.NET3.5的程序。奇怪的是,如果我切换到.NET4、4.5或4.5.1,进程会更快地泄漏内存

有人能理解为什么会发生这种情况,以及如何解决它(或者至少解决它)

示例代码如下所示:

using System;
using System.ServiceModel;

namespace memoryleak
{
    internal class Program
    {
        private static void Main()
        {
            using (var hostA = new ServiceHost(new ServiceA(), new Uri("net.pipe://localhost")))
            using (var hostB = new ServiceHost(new ServiceB(), new Uri("net.pipe://localhost")))
            {
                hostA.AddServiceEndpoint(typeof (ContractA), new NetNamedPipeBinding(), "test_service_a");
                hostA.Open();
                hostB.AddServiceEndpoint(typeof (ContractB), new NetNamedPipeBinding(), "test_service_b");
                hostB.Open();

                while(true)dowork();
            }
        }

        //CALLING SERVICE A

        //uncomment the following line to reuse the same ChannelFactory each time
        //private static readonly ChannelFactory<ContractA> pipeFactory=new ChannelFactory<ContractA>(new NetNamedPipeBinding(),new EndpointAddress("net.pipe://localhost/test_service_a"));

        private static void dowork()
        {
            //comment the following line to reuse the same ChannelFactory each time
            var pipeFactory = new ChannelFactory<ContractA>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/test_service_a"));

            ContractA provider = null;
            try
            {
                provider = pipeFactory.CreateChannel();
                provider.DoWork();
            }
            catch
            {
            }
            finally
            {
                CloseChannel(provider);

                //comment the following line to reuse the same ChannelFactory each time
                try { pipeFactory.Close(); }catch{pipeFactory.Abort();}
            }
        }

        private static void CloseChannel(ContractA provider)
        {
            try
            {
                if (provider == null)
                    return;
                try
                {
                    ((IClientChannel) provider).Close();
                }
                catch
                {
                    ((IClientChannel) provider).Abort();
                }
                ((IDisposable) provider).Dispose();
            }
            catch (Exception ex)
            {
                throw new Exception("Error while closing channel", ex);
            }
        }
    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class ServiceA : ContractA
    {
        //CALLING SERVICE B


        //uncomment the following line to reuse the same ChannelFactory each time
        //private readonly ChannelFactory<ContractB> pipeFactory=new ChannelFactory<ContractB>(new NetNamedPipeBinding(),new EndpointAddress("net.pipe://localhost/test_service_b"));

        public void DoWork()
        {
            //comment the following line to reuse the same ChannelFactory each time
            var pipeFactory=new ChannelFactory<ContractB>(new NetNamedPipeBinding(),new EndpointAddress("net.pipe://localhost/test_service_b"));

            ContractB provider = null;
            try
            {
                provider = pipeFactory.CreateChannel();
                provider.DoWork();
            }
            catch
            {
            }
            finally
            {
                CloseChannel(provider);

                //comment the following line to reuse the same ChannelFactory each time
                try { pipeFactory.Close(); } catch { pipeFactory.Abort(); }
            }
        }

        private void CloseChannel(ContractB provider)
        {
            try
            {
                if (provider == null)
                    return;
                try
                {
                    ((IClientChannel) provider).Close();
                }
                catch
                {
                    ((IClientChannel) provider).Abort();
                }
                ((IDisposable) provider).Dispose();
            }
            catch (Exception ex)
            {
                throw new Exception("Error while closing channel", ex);
            }
        }

    }

    [ServiceContract]
    public interface ContractA
    {
        [OperationContract]
        void DoWork();
    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class ServiceB : ContractB
    {
        public void DoWork()
        {
        }
    }

    [ServiceContract]
    public interface ContractB
    {
        [OperationContract]
        void DoWork();
    }
}
使用系统;
使用System.ServiceModel;
名称空间内存
{
内部课程计划
{
私有静态void Main()
{
使用(var hostA=new ServiceHost(new ServiceA(),new Uri)(“net。pipe://localhost")))
使用(var hostB=newservicehost(newserviceb(),newuri)(“net。pipe://localhost")))
{
AddServiceEndpoint(typeof(ContractA),新的NetNamedPipeBinding(),“测试服务a”);
hostA.Open();
hostB.AddServiceEndpoint(typeof(ContractB),新的NetNamedPipeBinding(),“测试服务”);
hostB.Open();
而(正确的)道工();
}
}
//呼叫服务A
//取消注释以下行以每次重复使用相同的ChannelFactory
//私有静态只读ChannelFactory pipeFactory=新的ChannelFactory(新的NetNamedPipeBinding(),新的EndpointAddress(“net”)。pipe://localhost/test_service_a"));
私有静态void dowork()
{
//注释下一行,以便每次重复使用相同的ChannelFactory
var pipeFactory=newchannelfactory(new NetNamedPipeBinding(),new EndpointAddress(“net。pipe://localhost/test_service_a"));
ContractA provider=null;
尝试
{
provider=pipeFactory.CreateChannel();
provider.DoWork();
}
抓住
{
}
最后
{
关闭频道(提供商);
//注释下一行,以便每次重复使用相同的ChannelFactory
尝试{pipeFactory.Close();}捕获{pipeFactory.Abort();}
}
}
专用静态无效关闭通道(ContractA提供程序)
{
尝试
{
if(提供程序==null)
返回;
尝试
{
((IClientChannel)提供程序).Close();
}
抓住
{
((IClientChannel)提供程序).Abort();
}
((IDisposable)provider.Dispose();
}
捕获(例外情况除外)
{
抛出新异常(“关闭通道时出错”,ex);
}
}
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,ConcurrencyMode=ConcurrencyMode.Multiple)]
公共类服务A:ContractA
{
//呼叫服务B
//取消注释以下行以每次重复使用相同的ChannelFactory
//私有只读ChannelFactory pipeFactory=新的ChannelFactory(新的NetNamedPipeBinding(),新的EndpointAddress(“net”)。pipe://localhost/test_service_b"));
公共工作
{
//注释下一行,以便每次重复使用相同的ChannelFactory
var pipeFactory=newchannelfactory(new NetNamedPipeBinding(),new EndpointAddress(“net。pipe://localhost/test_service_b"));
ContractB provider=null;
尝试
{
provider=pipeFactory.CreateChannel();
provider.DoWork();
}
抓住
{
}
最后
{
关闭频道(提供商);
//注释下一行,以便每次重复使用相同的ChannelFactory
尝试{pipeFactory.Close();}捕获{pipeFactory.Abort();}
}
}
私人频道(ContractB提供商)
{
尝试
{
if(提供程序==null)
返回;
尝试
{
((IClientChannel)提供程序).Close();
}
抓住
{
((IClientChannel)提供程序).Abort();
}
((IDisposable)provider.Dispose();
}
捕获(例外情况除外)
{
抛出新异常(“关闭通道时出错”,ex);
}
}
}
[服务合同]
公共接口合同
{
[经营合同]
无效销钉();
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,ConcurrencyMode=ConcurrencyMode.Multiple)]
公共类服务B:ContractB
{
公共工作
{
}
}
[服务合同]
公共接口合同
{
[经营合同]
无效销钉();
}
}
可能会发生什么
<configuration>
   <runtime>
      <gcServer enabled="true"/>
   </runtime>
</configuration>