我正在尝试通过网络制作一个小应用程序来提供整个屏幕的截图。我希望它能够通过LAN每1-2秒服务一次。我认为它不会成为一个大问题,所以我选择了C#和nancy www self host(作为最简单的选项)。现在,速度可以满足我的需求,但它似乎占用了太多的内存,而且随着时间的推移而增长。它似乎决定占用大约3.5 GB的内存,从那时起不再增长,但这是不可接受的数量 - 即使分辨率很高(我的是2560x1440)。
我的代码是坏的,还是不适合处理很多大的响应,或者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)
};
}
};
}
}
答案 0 :(得分:1)
尽可能将变量保留在最本地范围内,并尽可能处置。
您的部分问题可能是您重复使用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)
};
}