Tag: 垃圾收集

为什么WeakReference.IsAlive变得虚假?

作为这个问题的后续,我有以下代码: using System; using System.Runtime.InteropServices; namespace ConsoleApplication1 { class Program { class Child { public override string ToString() { return “I am a child!”; } ~Child() { Console.WriteLine(“~Child called”); } } class Test { readonly object _child; readonly WeakReference _ref; readonly GCHandle _gch; // GCHandle is a value type, so it’s safe public Test() { […]

ConcurrentDictionary似乎在删除时不标记GC的元素

我惊讶地发现我的应用程序内存占用不断增长 – 运行的时间越长,消耗的内存就越多。 因此,通过windbg一些魔力,我根据ConcurrentDictionary向我的小LRU缓存指出了一个问题。 CD有很多好处,对我来说非常酷(其中一个是它的数据永远不会在LOH中结束)。 TryRemove和TryRemove是用于添加和逐出项目的两种方法。 一些旧元素的!gcroot引导我回到我的缓存。 ILSpy的一些调查让我得出了这样的结论: TryRemove并没有真正删除元素。 它只是改变链表指针以跳过从不将数组元素的值赋值为null 。 这可以防止GC收集旧的被驱逐的对象。 真? 这是一个已知的问题吗? 如果是这样,我唯一的选择是TryUpdate(key, null) ,然后是TryRemove(key) ? 如果是这样,那么我必须锁定ConcurrentDictionary访问,这是矛盾的。 这是ILSpy转储: // System.Collections.Concurrent.ConcurrentDictionary private bool TryRemoveInternal(TKey key, out TValue value, bool matchValue, TValue oldValue) { while (true) { ConcurrentDictionary.Tables tables = this.m_tables; int num; int num2; this.GetBucketAndLockNo(this.m_comparer.GetHashCode(key), out num, out num2, tables.m_buckets.Length, tables.m_locks.Length); lock (tables.m_locks[num2]) { […]

如何确保winform被垃圾收集?

正如我从在线和我的个人实验中学到的那样,表单(System.Windows.Forms.Form)的终结器永远不会被GC调用。 据说在Form GC.SuppressFinalize()的Dispose()内部被调用,因此不会再次调用终结器。 Exapmle: public partial class UpdateForm : Form { public UpdateForm() { InitializeComponent(); // Listen to the event of some model Database.OnDataUpdated += new EventHandler(DataBase_OnDataUpdated); } ~UpdateForm() { // Never gets called. } private void DataBase_OnDataUpdated(object sender, EventArgs e) { // Update data on this form } } 但是,如上面的示例所示,如果表单连接(+ =)某个模型的事件并且不断开( – =)Dispose()中的事件,则表单永远不会被垃圾回收,即使Dispose(被叫。 我要做的是检查表单是否真的是垃圾收集的是我在表单中创建一个大数组以消耗大量内存,如下所示: […]

如何以及何时为WinForms控件处理Font

当分配任何控件的Font属性时,静态代码分析工具(来自HP的Fortify)抱怨Visual Studio Designer生成的WinForms代码。 分析工具抱怨: line 143: this.mCopyrightLabel.Font = new System.Drawing.Font(“Microsoft Sans Serif”, 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0))); AboutWindowForm.cs中的函数InitializeComponent()无法正确处理第143行上Font()分配的非托管系统资源。 说明: 该程序无法正确处置使用非托管系统资源的托管对象。 无法正确处置使用非托管系统资源的托管对象至少有两个常见原因: 错误条件和其他特殊情况。 混淆程序的哪个部分负责释放资源。 在这种情况下,有一些程序路径,在第143行的AboutWindowForm.cs中分配的资源没有正确处理。 托管.NET对象的一小部分使用非托管系统资源。 .NET的垃圾收集器可能无法以可预测的方式释放原始托管对象。 因此,应用程序可能耗尽可用内存,因为垃圾收集器不知道非托管资源所消耗的内存。 大多数非托管资源泄漏问题导致一般软件可靠性问题,但如果攻击者可以故意触发非托管资源泄漏,则攻击者可能会通过耗尽非托管资源池来启动拒绝服务攻击。 我已经搜索了关于在Windows窗体中处理字体一段时间的主题,这些是我收集的要点: 创建字体将占用GDI对象,这是一个非托管资源,因此在不再需要时释放非常重要 由于GDI对象昂贵且稀缺,WinForm会缓存它们。 Dispose WinForms控件还将处理其所有子控件并“释放获得的非托管资源” 如果表格是无模式的,表格将在关闭时处理 因此,我想得出结论,在VS生成的代码中没有必要显式分配给控件的Font,并且我们不应该这样做,因为字体是缓存的? 我创建了一个非常简单的表单测试程序:通过单击一个按钮,我创建了一个使用不同字体的新空表单。 关闭新打开的表单后,任务管理器中的GDI对象计数立即关闭。 这是上述要点的证据,不是吗? 然而静态分析仪似乎不相信。 它认为Font最终将由GC发布。 它还认为这对非托管资源不利,因为消耗的内存位于GC的知识之外,因此GC不会及时触发,因为GC感觉没有内存压力。 这为攻击者提供了故意触发耗尽非托管池的机会。 你能帮我理解分析仪给出的解释吗? 它对WinFroms有效吗? 手动处理创建的每个Font会很繁琐。 确切地说: 在控件的Dispose期间是否立即明确地处理Font,或者Control释放对Font的引用并让GC处理所有左边的? 谢谢! 我的问题的进一步更新:我做的另一个实验是:我在TaskManager和内存分析器中监视我的测试WinForm应用程序。 主窗体有一个按钮,用于打开另一个窗体,其单击时字体不同。 我注意到当我单击按钮并打开新窗体时,TaskManager中的GDI对象计数会增加。 因此,内存分析器观察到Font对象的计数。 但是,当我关闭新窗体时,TaskManager中的GDI对象数量立即下降。 内存探查器中Font对象的数量没有变化,这意味着GC没有发生。 但是,这些Font对象在内存分析器中被标记为“已处置但未收集”。 它给我这种感觉,当Form关闭时,Font对象设置为WinForms […]

收集仍在范围内的对象 – GC.Collect

我读过这篇文章: http : //blogs.msdn.com/b/oldnewthing/archive/2010/08/10/10048149.aspx老实说我并不了解每一个细节。 据我所知,在下面的代码中,即使我没有将c设置为null,也应该收集c。 另一件事是,只要我们处于同一函数的范围内,在foreach期间发生的分配似乎不会被释放。 (见下面的例子) class Program { public class SomeClass { public byte[] X; public SomeClass() { X = new byte[1024 * 1024 * 100]; X[155] = 10; } } static void Main() { Console.WriteLine(“Memory: ” + GC.GetTotalMemory(false)); SomeClass c; c = new SomeClass(); Console.WriteLine(“Memory: ” + GC.GetTotalMemory(false)); GC.Collect(); Console.WriteLine(“Memory: ” + […]

Monodroid:执行完整的GC

我尝试创建我的小粒子系统。 我有粒子列表的粒子管理器,并在canvas上绘制我的粒子。 我只是在init()函数中创建了一些像Paint等新对象! 如果粒度<0,我将其删除: for (int particle = 0; particle 0 ? true : false { particles[particle] = null; //here I tried all variations like //((IDisposable)particles[particle]).Dispose(); //GC.SuppressFinalize(particles[particle]); //System.GC.ReRegisterForFinalize(particles[particle]); //((Java.Lang.Object)particles[particle]).Dispose(); and etc particles.Remove(particles[particle]); } 然后我创建新的粒子并将其添加到我的列表中。 我在日志中看到的内容: GC cleanup summary: 1063 objects tested – resurrecting 1002. GC cleanup summary: 1053 objects tested – resurrecting 992. … GC […]

有没有办法显示“阻止”WinForms ContextMenu?

有没有办法显示ContextMenu并阻止进一步执行,直到选择了一个项目? 特别是,我希望获得类似于ShowDialog()行为,但是对于ContextMenu 。 直接的方法不起作用: ContextMenu cm = new ContextMenu(); cm.MenuItems.Add(“1”, (s,e) => {value = 1;}); cm.Show(control, location); 因为Click回调不是直接从Show()调用,而是在消息循环处理click事件时稍后调用。 如果你运气不好, menu会在事件处理之前被垃圾收集,在这种情况下,事件就会无声地丢失。 (这意味着你不能以这种方式真正使用ContextMenu的局部变量。) 这似乎有效,但感觉“不洁”: using (ContextMenu cm = new ContextMenu()) { cm.MenuItems.Add(“1”, (s,e) => {value = 1;}); cm.Show(control, location); Application.DoEvents(); } 有没有更好的办法?

C# – 是否可以迭代GC堆?

我不确定以下问题是否有效。为了教育自己,我只是在问。 (1)我可以以编程方式迭代所有代的GC堆吗? (2)是否可以通过启动线程来观察GC如何对我的组件进行操作?

我如何明确清除字节

我正在创建新的字节数组,这些数组不是由GC收集的,而是存在于内存中并增加了专用字节。 下面的代码每10秒执行一次。 完成后如何明确清除变量? byte[] outputMessage = new byte[10000]; //Do some work here

这里是否需要GC.KeepAlive,或者我可以依赖本地和参数来保持对象存活吗?

我有一堆方法使用不安全的代码直接使用WPF的WriteableBitmap并从其BackBuffer读取。 每当我做这样的事情时,我是否应该使用GC.KeepAlive并不完全清楚: int MyMethod(WriteableBitmap bmp) { return DoUnsafeWork(bmp.BackBuffer); } 一方面,在MyMethod的堆栈上仍然存在对bmp的引用。 另一方面,它似乎依赖于实现细节 – 这可以编译为尾调用,例如,在输入DoUnsafeWork不保留对bmp的引用。 同样,想象下面的假设代码: int MyMethod() { WriteableBitmap bmp1 = getABitmap(); var ptr = bmp.BackBuffer; WriteableBitmap bmp2 = getABitmap(); return DoUnsafeWork(ptr, bmp2); } 理论上,在方法返回之前,对bmp1的引用仍保留在堆栈中,但同样,它似乎使用了实现细节。 当然编译器可以自由地合并bmp1和bmp2因为它们永远不会同时存在,即使编译器从来没有这样做,JITter仍然可以,并且可能确实如此(例如,通过将它们存储在同一个寄存器中,一个,然后另一个)。 所以,一般来说:我应该依赖locals / arguments作为对象的有效引用,还是应该总是使用GC.KeepAlive来保证正确性? 这尤其令人费解,因为显然, FxCop认为GC.KeepAlive总是很糟糕 。