发送屏幕截图占用太多内存
本文关键字:太多 内存 屏幕截图 | 更新日期: 2023-09-27 17:59:43
我正在尝试制作一个小型应用程序,通过网络提供整个屏幕的截图。我希望它能够通过局域网每1-2秒服务一次。我认为这不会是一个大问题,所以我选择了C#和NancyWWW自主机(作为最简单的选择)。现在,速度可以满足我的需求,但它似乎占用了太多的内存,而且它会随着时间的推移而增长。它似乎决定占用大约3.5 GB的RAM,从此不再增长,但这是一个不可接受的数量——即使是大分辨率(我的是2560x1440)。
是我的代码不好,还是nancy不适合处理许多大的响应,或者是C#的屏幕捕获方法优化得不好,我应该尝试pinvoke方法?或者这只是一种糟糕的方法,我应该尝试更高级的方法,比如使用VNC库?
目前我的代码如下:
public class HomeModule : NancyModule
{
private Bitmap bitmapScreenCapture;
private Graphics graphics;
private Object lockMe = new object();
private MemoryStream memoryStream = new MemoryStream();
public HomeModule()
{
Get["image"] = parameters =>
{
lock (lockMe)
{
GC.Collect();
if (bitmapScreenCapture == null || bitmapScreenCapture.Width != Screen.PrimaryScreen.Bounds.Width || bitmapScreenCapture.Height != Screen.PrimaryScreen.Bounds.Height)
{
if (bitmapScreenCapture != null)
{
bitmapScreenCapture.Dispose();
}
bitmapScreenCapture = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
graphics = Graphics.FromImage(bitmapScreenCapture);
}
graphics.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0, 0,
bitmapScreenCapture.Size,
CopyPixelOperation.SourceCopy);
bitmapScreenCapture.Save(memoryStream, ImageFormat.Png);
memoryStream.Position = 0;
return new Response()
{
Contents = stream => memoryStream.CopyTo(stream)
};
}
};
}
}
尽可能地将变量保持在最局部的范围内,并尽可能地处理掉。
问题的一部分可能是您正在重复地新建Graphics
实例,但从未处理旧引用。GC最终会收集它,但您可以将代码放在using
块中,让它知道您已经完成了它
我还没有对此进行测试,但在这里我已经将您的实例设置为本地实例,并处理了Graphics
和Bitmap
实例。我没有处理MemoryStream
,因为我不确定如果你这样做,它会成功返回值,但你可以玩它。
var screen = Screen.PrimaryScreen;
using (var bitmap = new Bitmap(screen.Bounds.Width, screen.Bounds.Height))
{
using (var g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(screen.Bounds.Left, screen.Bounds.Top, 0, 0, screen.Bounds.Size);
}
var imageStream = new MemoryStream();
bitmap.Save(imageStream, ImageFormat.Png);
imageStream.Position = 0;
return new Response()
{
Contents = stream => memoryStream.CopyTo(stream)
};
}