2

这是我的场景:

  1. 启动我的测试程序并立即进入调试器(WinDBG)
  2. 使用 !DumpHeap -stat 并观察任何地方都没有 System.Net* 或 System.Xml* 对象
  3. 创建我的 WCF 客户端,发出 WCF 请求
  4. 关闭 WCF 客户端并强制 GC。
  5. 以 !DumpHeap -stat 和观察者为例,内存中仍有大量 System.Net*、System.Xml* 对象。

因此,从我在步骤 5 中的观察来看,WCF 似乎没有正确清理(或者更有可能我遗漏了一些东西)。为什么是这样?我怎样才能回收这些不应该在这里的对象占用的内存?

这是我的测试代码...

class Program
{
    static void Main(string[] args)
    {
        Debugger.Break();
        // !DumpHeap -stat here indicates no System.Net* or System.Xml* objects


        BasicHttpBinding binding = new BasicHttpBinding();
        binding.Security.Mode = BasicHttpSecurityMode.None;
        binding.UseDefaultWebProxy = false;
        WcfClient client = new WcfClient(
            binding, new EndpointAddress("http://myserver.com/service.svc"));
        client.Endpoint.Binding = binding;
        client.GetChain(new GetChainType()); // WCF call

        // my ineffective clean up code
        client.Close();
        client = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();


        // !DumpHeap -stat here indicates many System.Net* or System.Xml* objects

        Console.WriteLine("Request complete, press enter to quit");
        Console.ReadLine();
    }
}

PS 这是我的 !FinalizeQueue 结果...不确定这是否相关

0:010> !FinalizeQueue
SyncBlocks to be cleaned up: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
----------------------------------
generation 0 has 1 finalizable objects (000000001b1527f8->000000001b152800)
generation 1 has 81 finalizable objects (000000001b152570->000000001b1527f8)
generation 2 has 0 finalizable objects (000000001b152570->000000001b152570)
Ready for finalization 0 objects (000000001b152800->000000001b152800)
Statistics:
              MT    Count    TotalSize Class Name
000007fef033d078        1           32 Microsoft.Win32.SafeHandles.SafePEFileHandle
000007fef0326ab0        1           32 System.Security.Cryptography.SafeProvHandle
000007fef0326680        1           32 Microsoft.Win32.SafeHandles.SafeTokenHandle
000007feef7a2c18        1           32 Microsoft.Win32.SafeHandles.SafeProcessHandle
000007feef7a2b78        1           32 Microsoft.Win32.SafeHandles.SafeFileMapViewHandle
000007feef7a2ad8        1           32 Microsoft.Win32.SafeHandles.SafeFileMappingHandle
000007feef793510        1           32 System.Net.SafeLocalFree
000007feef78d980        1           40 System.Net.SafeCloseSocket
000007feef7a34e8        1           48 Microsoft.CSharp.CSharpCodeProvider
000007fef030fb18        2           64 Microsoft.Win32.SafeHandles.SafeFileMappingHandle
000007fef030fa78        2           64 Microsoft.Win32.SafeHandles.SafeViewOfFileHandle
000007feef791048        1           80 System.Net.Sockets.NetworkStream
000007fef03101f8        3           96 Microsoft.Win32.SafeHandles.SafeFileHandle
000007feef78caa0        1          120 System.Net.Sockets.Socket
000007fef02fdd10        2          128 System.Threading.ReaderWriterLock
000007feef78f520        4          160 System.Net.SafeRegistryHandle
000007feef78cd08        5          160 System.Net.SafeCloseSocket+InnerSafeCloseSocket
000007feef78f368        4          192 System.Net.SafeCloseSocketAndEvent
000007fef03071f8        2          208 System.Threading.Thread
000007fef02ffc40        7          224 Microsoft.Win32.SafeHandles.SafeRegistryHandle
000007fef02f4978       10          320 Microsoft.Win32.SafeHandles.SafeWaitHandle
000007fef02fdc70       20          640 System.WeakReference
000007feef7a1de0       10         1680 System.Diagnostics.PerformanceCounter
Total 82 objects

添加我认为应该消失的随机对象的 !GCRoot 跟踪...

0:010> !GCRoot -nostacks 000000000288e110 
DOMAIN(000000000020B2B0):HANDLE(Pinned):e17b8:Root:0000000012840770(System.Object[])->
00000000028b5380(System.Collections.Hashtable)->
00000000028b53d8(System.Collections.Hashtable+bucket[])->
00000000028b5528(System.Collections.Hashtable)->
00000000028b5580(System.Collections.Hashtable+bucket[])->
00000000028c1f68(Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer)->
0000000002898a38(System.Xml.Serialization.XmlMembersMapping)->
0000000002898a70(System.Object[])->
0000000002898a98(System.Xml.Serialization.XmlMemberMapping)->
0000000002896950(System.Xml.Serialization.MemberMapping)->
00000000028b90a8(System.Object[])->
00000000028969b8(System.Xml.Serialization.ElementAccessor)->
0000000002896aa8(System.Xml.Serialization.StructMapping)->
0000000002895eb8(System.Xml.Serialization.StructMapping)->
00000000028928f8(System.Xml.Serialization.StructMapping)->
000000000288bd10(System.Xml.Serialization.StructMapping)->
0000000002890da8(System.Xml.Serialization.StructMapping)->
000000000288f8e8(System.Xml.Serialization.StructMapping)->
000000000288ea78(System.Xml.Serialization.StructMapping)->
000000000288dc70(System.Xml.Serialization.StructMapping)->
000000000288dd20(System.Xml.Serialization.NameTable)->
000000000288dd38(System.Collections.Hashtable)->
000000000288dd90(System.Collections.Hashtable+bucket[])->
000000000288e1f8(System.Xml.Serialization.AttributeAccessor)->
000000000288e2f0(System.Xml.Serialization.EnumMapping)->
000000000288e110(System.Xml.Serialization.TypeDesc)
4

5 回答 5

2

强制垃圾收集的必要性是什么?

如果您的 Channel 已关闭,CLR 将负责 GC。

看看这个>>>

于 2009-10-28T21:56:34.180 回答
1

你检查过根吗?

于 2009-10-28T22:19:44.077 回答
1

XmlSerializer 体系结构静态缓存有关它遇到的类型的各种信息,因此它不必经常创建序列化程序(这完全有道理),所以这些东西没有被清理对我来说并不奇怪。从您的 !GCRoot 转储中充斥着 System.Xml.Serialization 中的东西这一事实来看,这似乎肯定是罪魁祸首。

于 2009-10-28T23:33:02.290 回答
0

我在 WinForms 中进行跟踪时发现,您必须执行两次 GC.Collect() 并在其间使用 Application.DoEvents() 才能强制收集足够好,以便使用内存跟踪器来查找泄漏。

我敢打赌 WPF 也是如此。

于 2009-10-28T21:52:52.227 回答
0

在客户端调用 dispose 之前,您将客户端设置为 null。

于 2009-10-28T22:28:22.170 回答