C# 我得到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;

我想编写一个例程,从服务器(类似远程桌面)接收一些jpeg帧,将它们转换为位图图像,然后在windows窗体上显示它们。我正试图使程序尽可能轻松,但可能是我做错了,因为我总是收到System.OutOfMemoryException。我的代码如下:

编辑:添加了与此异常相关的零件

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:)编辑:我发现了一个错误。。现在我来看看它是否相关。。如果你添加一个答案,我会给你另一点,因为这是问题的一部分:)谢谢你我忘记了那个功能,谢谢:)是的,这不是一个好的实践,但可能在这里它是必要的我忘记了那个功能,谢谢:)是的,这不是一个好的实践,但可能在这里它是必要的再次感谢你的努力:)再次感谢你的努力:)