我想编写一个例程,以从服务器(远程桌面-类似)接收一些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;
    }

===============>>#1 票数:2 已采纳

当您使用基于GDI +的API(System.Drawing)时, OutOfMemory异常并不一定意味着您内存不足。 这也可能意味着传递给GDI +的参数无效或其他原因。 GDI +非常高兴OutOfMemory


如果可能,还应该重用您的内存流。 降低GC的压力很大 您正在分配许多大对象,在这种情况下,GC非常糟糕。


我也认为您永远不会处置lCurrent


然后,您违反了Image.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()

===============>>#2 票数:1

一旦我编写了一个程序,该程序处理了从文件加载的大量图像。 我会尽快Dispose所有事情,然后将其余的交给GC。 这还不够,内存使用情况分析清楚地表明,相对于我程序的图像加载速度,GC太慢。 解决的办法是,每当我处理完给定数量的图像时,便手动调用GC.Collect() 请注意, 这不是一个好习惯 ,但有时会有所帮助。 至少值得尝试。

===============>>#3 票数:1

该问题可能与二进制协议错误有关(视频长度以某种方式弄乱了,请参阅lBRVideo.ReadInt16和ReadInt32调用您将其注释掉)

  ask by gc5 translate from so

未解决问题?本站智能推荐:

关注微信公众号