WCF消息系列化泄漏事件句柄和非托管内存 [英] WCF Message serialization leaking event handles and unmanaged memory

查看:365
本文介绍了WCF消息系列化泄漏事件句柄和非托管内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个WCF客户端,我们需要保存请求之前,我们送它,但是每一个序列化之后也有一些泄露的Windows事件句柄。我们试过的WinDbg,但手柄由CLR创建的。使用Sysinternals的handles.exe显示,信号量和事件都在不断增加,非托管内存也在增加:

We have a WCF client and we need to save the request before we send it, however after every serialization there are some leaked windows event handles. We've tried windbg but the handles are created by the clr. Using sysinternals handles.exe reveals that Semaphores and Events are constantly increasing, the unmanaged memory is also increasing:

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 下面是测试code来说明这个问题:

After some testing, it seems that the behaviour occurs only on 4.0/4.5 Here is test code to demonstrate the problem:

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;
        }
    }
}

现在的问题是,我们是否做错了什么,或者是在框架中的一个错误?

The question is, are we doing something wrong, or is it a bug in the framework?

推荐答案

哦,原来我用Google搜索了一点:

Well, it turns out I should have googled a bit more:

http://www-jo.se/f.pfleger/memoryleak http://plainoldstan.blogspot.ch/2011/04/wcf - 内存泄漏,with.html

解决方案是缓存TypedMessageConverter,谁也能猜到。

The solution is to cache the TypedMessageConverter, who would have guessed.

这篇关于WCF消息系列化泄漏事件句柄和非托管内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆