C# 我得到System.OutOfMemoryException。有没有办法让我的代码更轻松?
我想编写一个例程,从服务器(类似远程桌面)接收一些jpeg帧,将它们转换为位图图像,然后在windows窗体上显示它们。我正试图使程序尽可能轻松,但可能是我做错了,因为我总是收到System.OutOfMemoryException。我的代码如下: 编辑:添加了与此异常相关的零件C# 我得到System.OutOfMemoryException。有没有办法让我的代码更轻松?,c#,windows,image,bitmap,out-of-memory,C#,Windows,Image,Bitmap,Out Of Memory,我想编写一个例程,从服务器(类似远程桌面)接收一些jpeg帧,将它们转换为位图图像,然后在windows窗体上显示它们。我正试图使程序尽可能轻松,但可能是我做错了,因为我总是收到System.OutOfMemoryException。我的代码如下: 编辑:添加了与此异常相关的零件 private void WatcherRoutine() { Boolean lLoopEnd = false; Bitmap lCurrent = null;
private void WatcherRoutine()
{
Boolean lLoopEnd = false;
Bitmap lCurrent = null;
//Graphics lGraphics = null;
Image lImg = null;
BinaryReader lBRVideo = new BinaryReader(this._state.Video.GetStream());
while (lLoopEnd == false)
{
try
{
// Reads frame type
switch (lBRVideo.ReadByte())
{
// Frame received is a big frame (ie a desktop screenshot)
case Constants.BIGFRAME:
{
// Reads frame size in bytes
Int32 lVideoLength = lBRVideo.ReadInt32();
if (lVideoLength > 0)
{
// Stores frame in a stream
MemoryStream ms = new MemoryStream(lBRVideo.ReadBytes(lVideoLength));
// Creates image from stream
lImg = Image.FromStream(ms);
ms.Dispose();
// Creates bitmap from image
lCurrent = new Bitmap(lImg);
lImg.Dispose();
// Passes image to windows form to display it
this.Invoke(this._state.dUpdateVideo, lCurrent);
////lGraphics = Graphics.FromImage(lImg);
//lGraphics.Dispose();
}
}
break;
// Diff frame (ie a small part of desktop that has changed)
// Commenting this part makes the exception disappear :|
case Constants.DIFFFRAME:
{
Int16 lX = lBRVideo.ReadInt16(),
lY = lBRVideo.ReadInt16();
Int32 lVideoLength = lBRVideo.ReadInt32();
if (lVideoLength > 0)
{
//Byte[] lVideoImg = lBRVideo.ReadBytes(lVideoLength);
//Image lImgDiff = Image.FromStream(new MemoryStream(lVideoImg));
////if(lGraphics != null)
//{
// lGraphics.DrawImage(lImgDiff, lX, lY);
// this.Invoke(this._state.dUpdateVideo, new Bitmap(lImg));
//}
}
}
break;
case Constants.CURSOR:
{
Int16 lX = lBRVideo.ReadInt16(),
lY = lBRVideo.ReadInt16();
// TODO
}
break;
default:
break;
}
}
catch (Exception e)
{
if (this._state.WorkEnd == false)
{
this._state.WorkEnd = true;
this.BeginInvoke(this._state.dDisconnect);
}
lLoopEnd = true;
SmartDebug.DWL(e.Message);
}
}
}
dUpdateVideo是一个包含此小例程的委托。。也许我必须释放pBmp
private void UpdateVideo(Bitmap pBmp)
{
this.VideoPictureBox.Image = pBmp;
}
有一次,我写了一个程序,处理从文件加载的大量图像。我
Dispose
d尽可能快地处理所有我能处理的事情,并将其余的交给GC。这还不够,内存使用情况分析清楚地表明,相对于我的程序的图像加载速度,GC太慢了。解决方案是每次处理完给定数量的图像后,手动调用GC.Collect()
。注意这一点,但有时会有所帮助。至少值得一试。有一次,我写了一个程序,处理从文件加载的大量图像。我Dispose
d尽可能快地处理所有我能处理的事情,并将其余的交给GC。这还不够,内存使用情况分析清楚地表明,相对于我的程序的图像加载速度,GC太慢了。解决方案是每次处理完给定数量的图像后,手动调用GC.Collect()
。注意这一点,但有时会有所帮助。至少值得一试。当您使用基于GDI+的API(System.Drawing)时,OutOfMemory
异常并不一定意味着您的内存不足。这也可能意味着传递给GDI+的参数无效,或者是其他原因。GDI+非常OutOfMemory
happy
如果可能的话,您还应该重用内存流。这大大降低了GC压力。您正在分配许多大型对象,在这种情况下,GC非常糟糕
此外,我认为您从未处理过当前的
lCurrent
那么您违反了
图像的约定。FromStream
:
您必须在映像的生命周期内保持流的打开状态:
lImg = Image.FromStream(ms);
ms.Dispose();
lCurrent = new Bitmap(lImg);// `lImage` is used here, but `ms` is already disposed
lImg.Dispose();
Image.FromStream
的文档说明:
您必须在映像的生命周期内保持流打开
当您使用基于GDI+的API(System.Drawing)时,
OutOfMemory
异常并不一定意味着您的内存不足。这也可能意味着传递给GDI+的参数无效,或者是其他原因。GDI+非常OutOfMemory
happy
如果可能的话,您还应该重用内存流。这大大降低了GC压力。您正在分配许多大型对象,在这种情况下,GC非常糟糕
此外,我认为您从未处理过当前的
lCurrent
那么您违反了
图像的约定。FromStream
:
您必须在映像的生命周期内保持流的打开状态:
lImg = Image.FromStream(ms);
ms.Dispose();
lCurrent = new Bitmap(lImg);// `lImage` is used here, but `ms` is already disposed
lImg.Dispose();
Image.FromStream
的文档说明:
您必须在映像的生命周期内保持流打开
将
ms.Dispose()
移到lImg.Dispose()
后面该问题可能与二进制协议错误有关(视频长度有点混乱,请参阅lBRVideo.ReadInt16和ReadInt32调用您的注释)该问题可能与二进制协议错误有关(视频长度有点混乱,请参见lBRVideo.ReadInt16和ReadInt32调用您的注释)不知道是否释放了LCurrentPeas使用的内存请提供dUpdateVideo的源,它也可能是内存泄漏的源。检查是否在lvideLength中接收到正确的数据(由于某些错误,可能是非常大的数字)我认为这是您的二进制协议的问题,视频长度不知怎么搞砸了(请参阅lBRVideo.ReadInt16和ReadInt32调用您的注释),现在我将检查thx:)编辑:我发现了一个bug。。现在我来看看它是否相关。。如果您添加一个答案,我将给您另一点,因为这是问题的一部分:)谢谢您不知道您是否释放了LCurrentPeas使用的内存。请提供dUpdateVideo的源,它也可能是内存泄漏的源。检查您是否收到正确的LVideLength数据(由于某些错误,它可能是一个非常大的数字),我认为这是您的二进制协议的问题,视频长度不知怎么搞砸了(请参阅lBRVideo.ReadInt16和ReadInt32调用您的注释),现在我将检查thx:)编辑:我发现了一个错误。。现在我来看看它是否相关。。如果你添加一个答案,我会给你另一点,因为这是问题的一部分:)谢谢你我忘记了那个功能,谢谢:)是的,这不是一个好的实践,但可能在这里它是必要的我忘记了那个功能,谢谢:)是的,这不是一个好的实践,但可能在这里它是必要的再次感谢你的努力:)再次感谢你的努力:)