C# 保存位图时是否会出现memoryleak?
我正在计算机上保存当前图像的屏幕截图:C# 保存位图时是否会出现memoryleak?,c#,image,memory-leaks,bitmap,C#,Image,Memory Leaks,Bitmap,我正在计算机上保存当前图像的屏幕截图: Rectangle bounds = Screen.GetBounds(Point.Empty); using (var bitmap = new Bitmap(bounds.Width, bounds.Height)) { using (Graphics g = Graphics.FromImage(bitmap)) { g.CopyFromScreen(Point.Empty, Point.Empty, bounds.S
Rectangle bounds = Screen.GetBounds(Point.Empty);
using (var bitmap = new Bitmap(bounds.Width, bounds.Height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size);
}
using (var mss = new MemoryStream())
{
bitmap.Save(mss,ImageFormat.Gif);
}
}
memoryleak位于以下代码处:
bitmap.Save(mss,ImageFormat.Gif);
我使用的using
不应该处理我正在使用的所有东西吗
为什么在拍摄大量照片时,我的内存使用率仍然很高,而内存却没有释放出来
谢谢大家! 您可能看到的问题与我询问时遇到的问题相同 在我的例子中,问题是
MemoryStream
即使在调用Dispose
时也没有释放其内部byte[]
。直到MemoryStream
超出范围并被GC收集,才会释放字节[]
详细说明问题的原因,并说明它对我有效,我怀疑您遇到了相同的问题。本质上,它将底层的MemoryStream
封装在一个实现相同接口的类型中,但在调用Dispose()
时将流引用设置为null。由于没有其他对象应该具有对内部流的实时引用,因此允许GC突袭并清理它
此外,内部
字节[]
很可能会分配到大型对象堆上,这会导致多次分配后出现碎片。您可以尝试使用BufferManager,它会为您管理字节[]
// declare the BufferManager somewhere. Check thread safety!
BufferManager bm = BufferManager.CreateBufferManager(qqq, yyy);
// wrap your current code to use the buffer manager
Rectangle bounds = Screen.GetBounds(Point.Empty);
using (var bitmap = new Bitmap(bounds.Width, bounds.Height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size);
}
byte[] buffer = bm.TakeBuffer(yyy);
try
{
using (MemoryStream stream = new MemoryStream(buffer))
{
bitmap.Save(mss,ImageFormat.Gif);
}
}
finally
{
bm.ReturnBuffer(buffer);
}
}
我在读,你知道吗,在你的情况下你用了整个班级吗?是的,我用了整个班级。我不知道你怎么能少拿一点。它继承自抽象的
流
类,因此您必须实现所有这些方法,这就是允许它被视为流的原因,即使所有实际工作都被传递下来。所以我将当前memorystream放在新的wrappedstream中,对吗?使用(WrappingStream wp=newwrappingstream(mss))尝试一下,就像那样。另外,如果你还没有准备好,我建议你使用一个分析器。这个产品非常棒,他们有14天的试用期(我不为他们工作,就像产品一样:)。你确定吗?此时,您需要通过探查器运行应用程序并返回结果。在您这样做之前,我们只是猜测。根本问题是:为什么您需要将位图存储到内存流中?为什么不只存储新字节[]?为什么是BufferManager?它将1)返回长度为1米、2米、4米、8米、16米等的缓冲区(我假设缓冲区也小于1米,但没有验证),因此如果您要求9米,您将得到16米阵列。2) 缓冲区管理器永远不会自行清理,因此您必须手动调用BufferManager.clean()。另见和