Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.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消息序列化泄漏事件句柄和非托管内存_C#_Wcf_.net 4.0_Memory Leaks - Fatal编程技术网

C# WCF消息序列化泄漏事件句柄和非托管内存

C# WCF消息序列化泄漏事件句柄和非托管内存,c#,wcf,.net-4.0,memory-leaks,C#,Wcf,.net 4.0,Memory Leaks,我们有一个WCF客户端,我们需要在发送请求之前保存请求,但是在每次序列化之后都会有一些泄漏的windows事件句柄。我们尝试了windbg,但句柄是由clr创建的。使用sysinternals handles.exe可以发现信号量和事件不断增加,非托管内存也在增加: Handle type summary: ALPC Port : 10 Desktop : 1 Directory : 5 EtwRegistration : 16 Eve

我们有一个WCF客户端,我们需要在发送请求之前保存请求,但是在每次序列化之后都会有一些泄漏的windows事件句柄。我们尝试了windbg,但句柄是由clr创建的。使用sysinternals handles.exe可以发现信号量和事件不断增加,非托管内存也在增加:

Handle type summary:
  ALPC Port       : 10
  Desktop         : 1
  Directory       : 5
  EtwRegistration : 16
  Event           : 574
  File            : 12
  IoCompletion    : 3
  Key             : 13
  KeyedEvent      : 1
  Mutant          : 7
  Process         : 1
  Section         : 11
  Semaphore       : 467
  Thread          : 19
  Timer           : 3
  TpWorkerFactory : 16
  WindowStation   : 2
Total handles: 1161
经过一些测试后,该行为似乎只发生在4.0/4.5上 下面是演示问题的测试代码:

namespace HandleLeak
{
    class Program
    {
        private static XDocument SerializeToSoap(object source)
        {
            TypedMessageConverter messageConverter = TypedMessageConverter.Create(source.GetType(), null, new XmlSerializerFormatAttribute());
            using (Message request = messageConverter.ToMessage(source, MessageVersion.Soap11))
            {
                var xdoc = new XDocument();
                using (var wr = xdoc.CreateWriter())
                {
                    request.WriteMessage(wr);
                }
                return xdoc;
            }
        }

        static void Main(string[] args)
        {
            var sr = new SomeRequest();
            while(true)
            {
                SerializeToSoap(sr);
                GC.Collect();

                var currentProcess = Process.GetCurrentProcess();
                Console.WriteLine("Handles: {0}", currentProcess.HandleCount);
                Console.WriteLine("press any key to continue, esc to quit");
                if (Console.ReadKey(true).Key == ConsoleKey.Escape)
                    break;
            }
            Console.WriteLine("Done");
            Console.ReadKey();
        }
    }

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.1")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://test")]
    public partial class SomeType
    {

    }

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    [System.ServiceModel.MessageContractAttribute(IsWrapped = false)]
    public partial class SomeRequest
    {

        [System.ServiceModel.MessageBodyMemberAttribute(Name = "someRequest", Namespace = "http://test", Order = 0)]
        public SomeType statusRequest1;

        public SomeRequest()
        {
        }

        public SomeRequest(SomeType statusRequest1)
        {
            this.statusRequest1 = statusRequest1;
        }
    }
}
namespace HandleLeak
{
班级计划
{
私有静态XDocument序列化到OAP(对象源)
{
TypedMessageConverter messageConverter=TypedMessageConverter.Create(source.GetType(),null,新的XmlSerializerFormatAttribute());
使用(messagerequest=messageConverter.ToMessage(source,MessageVersion.Soap11))
{
var xdoc=new XDocument();
使用(var wr=xdoc.CreateWriter())
{
请求.书面信息(wr);
}
返回xdoc;
}
}
静态void Main(字符串[]参数)
{
var sr=new SomeRequest();
while(true)
{
Tosoap(sr);
GC.Collect();
var currentProcess=Process.GetCurrentProcess();
WriteLine(“句柄:{0}”,currentProcess.HandleCount);
Console.WriteLine(“按任意键继续,按esc退出”);
if(Console.ReadKey(true).Key==ConsoleKey.Escape)
打破
}
控制台。写入线(“完成”);
Console.ReadKey();
}
}
/// 
[System.CodeDom.Compiler.GeneratedCodeAttribute(“svcutil”,“4.0.30319.1”)]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute(“代码”)]
[System.Xml.Serialization.XmlTypeAttribute(命名空间=”http://test")]
公共部分类SomeType
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute(“System.ServiceModel”,“4.0.0.0”)]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
公共部分类请求
{
[System.ServiceModel.MessageBodyMemberAttribute(Name=“someRequest”,命名空间=”http://test“,顺序=0)]
公共SomeType statusRequest1;
公共请求()
{
}
公共SomeRequest(SomeType状态请求1)
{
this.statusRequest1=statusRequest1;
}
}
}

问题是,我们是做错了什么,还是它是框架中的一个bug?

嗯,事实证明我应该在谷歌上搜索更多:


解决方案是缓存TypedMessageConverter,谁会猜到呢。

在我们的情况下,我们也有同样的漏洞。使用第1篇文章中建议的另一个构造函数XmlSerializer.XmlSerializer(类型)就可以做到这一点。谢谢