में प्रयोग किया जाता है, तो मैं System.Threading.ThreadLocal<T>
से संबंधित कचरा कलेक्टर के इस अजीब 'व्यवहार' में आया हूं, जिसे मैं समझा नहीं सकता। सामान्य परिस्थितियों में, ThreadLocal<T>
उदाहरण जब वे दायरे से बाहर निकलते हैं तो कचरा इकट्ठा किया जाएगा, भले ही वे उचित तरीके से निपटान न हों, स्थिति को छोड़कर जहां वे चक्रीय वस्तु ग्राफ का हिस्सा हैं।मेमोरी लीक जब थ्रेडलोकल <T> चक्रीय ग्राफ
निम्न उदाहरण समस्या को दर्शाता है:
public class Program
{
public class B { public A A; }
public class A { public ThreadLocal<B> LocalB; }
private static List<WeakReference> references = new List<WeakReference>();
static void Main(string[] args) {
for (var i = 0; i < 1000; i++)
CreateGraph();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
// Expecting to print 0, but it prints 1000
Console.WriteLine(references.Count(c => c.IsAlive));
}
static void CreateGraph() {
var a = new A { LocalB = new ThreadLocal<B>() };
a.LocalB.Value = new B { A = a };
references.Add(new WeakReference(a));
// If either one of the following lines is uncommented, the cyclic
// graph is broken, and the programs output will become 0.
// a.LocalB = null;
// a.LocalB.Value = null;
// a.LocalB.Value.A = null;
// a.LocalB.Dispose();
}
}
हालांकि बुला नहीं Dispose
अच्छा अभ्यास नहीं है, लेकिन इसे संसाधनों अंत में साफ करने के लिए (finalizer फोन करके) CLR के डिजाइन है, भले ही Dispose
नहीं बुलाया जाता है ।
ThreadLocal
इस संबंध में अलग तरीके से व्यवहार क्यों करता है और चक्रीय ग्राफ के मामले में ठीक तरह से निपटने पर मेमोरी लीक का कारण बन सकता है? क्या यह डिजाइन द्वारा है? और यदि हां, तो यह कहां दस्तावेज है? या क्या यह सीएलआर के जीसी में एक बग है?
(.NET 4.5 के तहत परीक्षण किया गया)।
[डेविड केन] (https://twitter.com/davkean) ने पुष्टि की कि यह एक बग है। – Steven
[क्लिक करें] (https://mobile.twitter.com/davkean/status/655067698511024128)। – Steven