相关疑难解决方法(0)

即使在需要时也不会发生垃圾收集

我制作了一个64位WPF测试应用程序.随着我的应用程序运行并打开任务管理器,我会查看系统内存使用情况.我看到我使用2GB,我有6GB可用.

在我的应用程序中,我单击"添加"按钮将新的1GB字节数组添加到列表中.我看到我的系统内存使用量增加了1GB.我点击添加总共6次,填充我开始时可用的6GB内存.

我单击"删除"按钮6次,从列表中删除每个数组.删除的字节数组不应该由我的控件中的任何其他对象引用.

当我删除时,我没有看到我的记忆下降.但这对我来说没关系,因为我知道GC是非确定性的,所有这一切.我认为GC会根据需要收集.

所以现在内存看起来很满,但是期望GC在需要时收集,我再次添加.我的电脑开始滑入和跳出磁盘晃动昏迷.为什么GC不收集?如果不是时候做,那么什么时候?

作为一个完整性检查,我有一个强制GC的按钮.当我推动它时,我很快就恢复了6GB.这不能证明我的6个阵列没有被引用,并且如果GC知道/想要收集COULD吗?

我已经阅读了很多说我不应该调用GC.Collect()但是如果GC在这种情况下不收集,我还能做什么?

    private ObservableCollection<byte[]> memoryChunks = new ObservableCollection<byte[]>();
    public ObservableCollection<byte[]> MemoryChunks
    {
        get { return this.memoryChunks; }
    }

    private void AddButton_Click(object sender, RoutedEventArgs e)
    {
        // Create a 1 gig chunk of memory and add it to the collection.
        // It should not be garbage collected as long as it's in the collection.

        try
        {
            byte[] chunk = new byte[1024*1024*1024];

            // Looks like I need to populate memory otherwise it doesn't show up in task …
Run Code Online (Sandbox Code Playgroud)

.net c# memory garbage-collection

25
推荐指数
2
解决办法
8695
查看次数

在C#中进行大型,快速和频繁的内存分配时避免OutOfMemoryException

我们的应用程序不断为大量数据(比如几十到几百兆字节)分配数组,这些数据在丢弃之前会存在很短的时间.

天真地做这会导致大对象堆碎片,最终导致应用程序崩溃与OutOfMemoryException,尽管当前活动对象的大小不会过多.

我们过去成功管理过这种方法的一种方法是对阵列进行分块以确保它们不会最终出现在LOH上,其目的是通过允许内存被垃圾收集器压缩来避免碎片化.

我们的最新应用程序处理的数据比以前更多,并且在单独的AppDomain或单独进程中托管的加载项之间非常频繁地传递此序列化数据.我们采用了与以前相同的方法,确保我们的内存总是被分块并且非常小心地避免大对象堆分配.

但是我们有一个必须在外部32位进程中托管的加载项(因为我们的主应用程序是64位,加载项必须使用32位库).在特别繁重的负载下,当很多SOH内存块被快速分配并在之后不久丢弃时,即使我们的分块方法还不足以保存我们的32位加载项,并且它会因OutOfMemoryException而崩溃.

在发生OutOfMemoryException时使用WinDbg,!heapstat -inclUnrooted显示如下:

Heap             Gen0         Gen1         Gen2          LOH
Heap0           24612      4166452    228499692      9757136

Free space:                                                 Percentage
Heap0              12           12      4636044        12848SOH:  1% LOH:  0%

Unrooted objects:                                           Percentage
Heap0              72            0         5488            0SOH:  0% LOH:  0%
Run Code Online (Sandbox Code Playgroud)

!dumpheap -stat 显示这个:

-- SNIP --

79b56c28     3085       435356 System.Object[]
79b8ebd4        1      1048592 System.UInt16[]
79b9f9ac    26880      1301812 System.String
002f7a60       34      4648916      Free
79ba4944     6128     87366192 System.Byte[]
79b8ef28    17195    145981324 System.Double[]
Total 97166 objects
Fragmented blocks larger than 0.5 MB: …
Run Code Online (Sandbox Code Playgroud)

.net windbg out-of-memory fragmentation large-object-heap

12
推荐指数
1
解决办法
2600
查看次数

除了使用 P/Invoke 之外,如何在 hBitmap 上调用 DeleteObject()?

我正在处理类似这样的代码(从这里开始

using (var bmp = new System.Drawing.Bitmap(1000, 1000)) 
{
    IntPtr hBitmap = bmp.GetHbitmap(); 
    var source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
        hBitmap, IntPtr.Zero, Int32Rect.Empty,
        System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
}
Run Code Online (Sandbox Code Playgroud)

和MSDN说,每当我打电话Bitmap.GetHbitmap()我要叫DeleteObject()hBitmap释放非托管资源。

我看到的所有答案和 MSDN 都说我必须 P/InvokeDeleteObject()函数。这看起来有点疯狂,因为我获得了hBitmap没有 P/Invoke 的,现在我突然需要使用 P/Invoke 来正确摆脱它。

除了 P/Invoke 之外确实没有其他方法可以DeleteObject()调用 myhBitmap吗?

.net c# pinvoke bitmap hbitmap

5
推荐指数
1
解决办法
733
查看次数