0

我在 vb.net 中有以下代码:

Public Async Function WriteData(buffer() As Byte, offset As Integer, count As Integer) As System.Threading.Tasks.Task
        Try
            Using data_writer = IO.WindowsRuntimeStreamExtensions.AsStreamForWrite(_outputStream)
                Await data_writer.WriteAsync(buffer, offset, count)
                Await data_writer.FlushAsync
            End Using
        Catch ex As Exception
             Logger.Write(ex)
        End Try
    End Function

我调用函数 WriteDate 太多了,但我注意到每次调用该函数时内存都会增加,因为您可以看到数据写入器流和 _outputStream 因使用而被释放。

当我运行 vs Profiler 时,分析器显示 95% 的内存被我的代码中的“缓冲区”字节数组保留过多。

1-您在我的代码中看到任何问题吗?2-如何清除字节数组?

-- 我在 Await data_writer.FlushAsync 行之后向该函数添加了以下代码

buffer = Nothing
GC.Collect()

所以我的内存并没有像以前那样增加,但是我在我的应用程序中调用 WriteData 太多了,我读到不建议调用 GC.Collect 太多。

不调用 GC.Collect 内存会跳转到 300 MB,而 GC.Collect() 内存不会超过 50MB。

请指教。

谢谢

4

3 回答 3

3

在尝试控制 GC 之前,您应该了解它的工作方式。垃圾回收主要由“内存压力”驱动;也就是说,当你的程序内存不足时可以立即使用,会发生一个collection,以便释放一些。

您的内存使用量是 300MB 而没有调用GC.Collect的原因是因为 .NET 在运行代码时没有压力。因为它没有压力,所以不会浪费时间运行一个集合。分配的 300MB 内存没有被积极使用——你的代码并没有因为你在调用而神奇地更高效Collect——但是 .NET 没有理由在那时进行整理。

我的建议是:不要调用GC.Collect,除非您有特定且有意义的理由来减少应用程序的内存使用。需要时,垃圾收集器会自行收集该内存(您可能会看到使用量增加,然后定期回落到约 50MB)。

于 2013-04-08T10:44:37.123 回答
2

这是一个通用的 GC 问题,并非特定于 Phone 或 Await。虽然它肯定无助于解决问题。问题是您的缓冲区太大,超过 85KB。太大而无法被 GC 轻松压缩,因此它被分配在大对象堆中。现在第 0 代中没有足够的小对象来触发收集。LOH 仅在 gen#2 收集期间被清理,因此调用 GC.Collect() 确实是一种解决方法。

避免调用 Collect() 的两种基本策略。首先强烈支持使用较小的缓冲区,小到足以在 gen#0 中分配。做一点点工作总是更好,Await 关键字应该真的有助于在您的代码中进行微不足道的更改。很难说,我们看不到来电者。

第二种策略是重用缓冲区,因此您只需要其中一个。这又是多么容易,这在很大程度上取决于调用者的样子。

于 2013-04-08T11:27:11.647 回答
0

在另一种情况下,我遇到了同样的问题,使用 HTTP Server,但我找到了真正的解决方案:

永远不要使用 AsStreamForWrite(),直接使用 WinPRT IOuputStream(我想这是可能的,即使在 VB 中也是如此) AsStreamForWrite() 创建一个内部 Stream,它只会占用内存(在某些情况下)并且永远不会释放它。

于 2014-08-27T18:44:17.060 回答