नेट 4. थ्रेडलोकल <> आईडीआईएसपीबल लागू करता है। लेकिन ऐसा लगता है कि निपटान निपटाना() वास्तव में थ्रेड स्थानीय वस्तुओं के संदर्भों को संदर्भित नहीं करता है।थ्रेडलोकल <> और मेमोरी लीक
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
namespace ConsoleApplication2
{
class Program
{
class ThreadLocalData
{
// Allocate object in LOH
public int[] data = new int[10 * 1024 * 1024];
};
static void Main(string[] args)
{
// Stores references to all thread local object that have been created
var threadLocalInstances = new List<ThreadLocalData>();
ThreadLocal<ThreadLocalData> threadLocal = new ThreadLocal<ThreadLocalData>(() =>
{
var ret = new ThreadLocalData();
lock (threadLocalInstances)
threadLocalInstances.Add(ret);
return ret;
});
// Do some multithreaded stuff
int sum = Enumerable.Range(0, 100).AsParallel().Select(
i => threadLocal.Value.data.Sum() + i).Sum();
Console.WriteLine("Sum: {0}", sum);
Console.WriteLine("Thread local instances: {0}", threadLocalInstances.Count);
// Do our best to release ThreadLocal<> object
threadLocal.Dispose();
threadLocal = null;
Console.Write("Press R to release memory blocks manually or another key to proceed: ");
if (char.ToUpper(Console.ReadKey().KeyChar) == 'R')
{
foreach (var i in threadLocalInstances)
i.data = null;
}
// Make sure we don't keep the references to LOH objects
threadLocalInstances = null;
Console.WriteLine();
// Collect the garbage
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.WriteLine("Garbage collected. Open Task Manager to see memory consumption.");
Console.Write("Press any key to exit.");
Console.ReadKey();
}
}
}
थ्रेड स्थानीय डेटा स्टोर एक बड़ी वस्तु के लिए एक संदर्भ:
इस कोड को समस्या reproduces। यदि संदर्भ मैन्युअल रूप से रद्द नहीं किए जाते हैं तो जीसी इन बड़ी वस्तुओं को एकत्र नहीं करता है। मैंने मेमोरी खपत का निरीक्षण करने के लिए टास्क मैनेजर का इस्तेमाल किया। मैं मेमोरी प्रोफाइलर भी चलाता हूं। कचरा इकट्ठा करने के बाद मैंने एक स्नैपशॉट बनाया। प्रोफाइलर पता चला है कि लीक वस्तु GCHandle द्वारा निहित है और यहाँ के साथ आवंटित किया गया था:
mscorlib!System.Threading.ThreadLocal<T>.GenericHolder<U,V,W>.get_Boxed()
mscorlib!System.Threading.ThreadLocal<T>.get_Value()
ConsoleApplication2!ConsoleApplication2.Program.<>c__DisplayClass3.<Main>b__2(int) Program.cs
ThreadLocal < में एक दोष हो रहा है यही कारण है कि> डिजाइन। आगे सफाई के लिए सभी आवंटित वस्तुओं को स्टोर करने की चाल बदसूरत है। उस पर काम करने के तरीके पर कोई विचार?
आप डिबग में कर रहे हैं या इस के लिए जारी? भी, कार्य प्रबंधक –
को मापने के लिए वास्तव में बहुत उपयोगी नहीं है, आप स्मृति को मापने के लिए 'जीसी.गेटटॉटलमेमरी (सत्य)' का उपयोग करके बेहतर हैं, लेकिन यह भी गारंटी नहीं देता है कि सब कुछ एकत्र किया जाएगा। – Ray
मुद्रित जीसी। GetTotalMemory()। यह 335607644 देता है जब मैं शून्य ** डेटा ** फ़ील्ड और 63268 करता हूं जब मैं करता हूं। – SergeyS