لماذا لا يتم تنظيف هذه الموارد المتعلقة بـ WCF؟

StackOverflow https://stackoverflow.com/questions/1640256

سؤال

هنا هو السيناريو الخاص بي:

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

ملاحظة.هذه هي نتائجي!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)
هل كانت مفيدة؟

المحلول

تقوم بنية XmlSerializer بتخزين جميع أنواع المعلومات حول الأنواع التي واجهتها مؤقتًا بشكل ثابت بحيث لا تضطر دائمًا إلى إنشاء برامج تسلسل (وهو أمر منطقي تمامًا)، لذلك ليس من المفاجئ بالنسبة لي أن هذه الأشياء لا يتم تنظيفها.انطلاقًا من حقيقة أن تفريغ !GCRoot الخاص بك مليء بأشياء من System.Xml.Serialization، فمن المؤكد أنه يبدو أنه الجاني.

نصائح أخرى

ما هي ضرورة فرض جمع القمامة؟

إذا كانت قناتك مغلقة، فإن CLR يعتني بـ GC.

تحقق من ذلك >>>

هل تأكدت من الجذور؟

لقد اكتشفت عند التتبع في WinForms أنه كان عليك إجراء GC.Collect() مرتين باستخدام Application.DoEvents() بينهما لفرض التجميع بشكل جيد بما يكفي لاستخدام أداة تتبع الذاكرة للبحث عن التسريبات.

أراهن أن الشيء نفسه ينطبق على WPF.

أنت تقوم بتعيين العميل على القيمة الخالية، قبل أن يتم استدعاء التخلص من العميل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top