Graphics.DrawImage() 方法内存泄露

starssn 2015-02-04 04:33:48
在循环中调用Drawimage方法,进行图像的拼接,内存上涨很快,请问什么原因啊
...全文
1179 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
汤圆学Java 2017-08-08
  • 打赏
  • 举报
回复
引用 3 楼 csz_1987 的回复:
用using语句块啊

using(Graphic g = CreateGraphic)
{
    //出了语句块自动Dispose
}
正解啊,谢谢啦
lsx_workroom 2016-11-16
  • 打赏
  • 举报
回复
引用 3 楼 csz_1987 的回复:
用using语句块啊

using(Graphic g = CreateGraphic)
{
    //出了语句块自动Dispose
}
解决了我的问题.这个好办法.
phommy 2015-02-05
  • 打赏
  • 举报
回复
工程属性->代码分析->启用 选所有规则,编译 其中一条检查,凡是可以Dispose的,你没有Dispose就会有一条提示。先利用这个排查一下吧
於黾 2015-02-05
  • 打赏
  • 举报
回复
眼晕!好多Dispose和=null 建议你不要定义成全局变量然后在循环里反复使用 在循环里定义,用using包起来,这样不需要手动去释放,也不会不小心漏掉了某个变量的释放代码 更不会因为执行过程中出错而不执行释放的代码 finally是对应try的 只有在try里出错时,finally不管是否出错都会执行 而如果在执行try之前就已经出错,那么finally也不会执行
starssn 2015-02-05
  • 打赏
  • 举报
回复
怎么没人管我了啊,大神们
starssn 2015-02-05
  • 打赏
  • 举报
回复
找到原因了: 在调用此句的时候,应该删除取得的GDI对象


screenfrag = Image.FromHbitmap(bm.GetHbitmap());

修改后代码 引用gid32.dll 中的Deleteobject(IntPtr hObject)


Intptr  iptr = bm.GetHbitmap();
screenfrag =  Image.FromHbitmap(iptr);
Deleteobject(iptr);
所以,以后一定不要用方法的返回值来做参数,产生泄露非常有隐蔽性。 谢谢各位了!也请给我更多的指导
starssn 2015-02-05
  • 打赏
  • 举报
回复
谢谢各位了,我先看看
starssn 2015-02-04
  • 打赏
  • 举报
回复
引用 20 楼 unearth 的回复:
难道写代码 非得在一个过程里面写完,可以分成好几个小的模块去写呀。
谢谢提醒了,以后我要注意了,时间紧的结果啊 , 哈哈
孤独de猫 2015-02-04
  • 打赏
  • 举报
回复
难道写代码 非得在一个过程里面写完,可以分成好几个小的模块去写呀。
starssn 2015-02-04
  • 打赏
  • 举报
回复


public void GetPageImage(string path)
        {
            //Test Is OK
            if (true)
            {
                bool flag = firstScreen;
                //m_browser.Navigate(url);
                ////浏览器Dom载入完毕
                //while (m_browser.ReadyState != WebBrowserReadyState.Complete)
                //{
                //    Application.DoEvents();
                //}
                mshtml.IHTMLDocument2 myDoc = (mshtml.IHTMLDocument2)m_browser.Document.DomDocument;

                //处理由于webbrowser上、左边框阴影带来的拼接bug
                int URLExtraHeight = 0;
                int URLExtraLeft = 0;

                if ((myDoc as HTMLDocumentClass).body == null)
                {
                    //写日志
                    EtlDataProcess.InsertMailErrLog("图片保存失败","【"+path+"】图片保存失败,可能是因为格式加载过长导致。");
                    return;
                }

                (myDoc as HTMLDocumentClass).body.setAttribute("scroll", "yes", 0);

                //document完整高度
                int heightsize = (int)(myDoc as HTMLDocumentClass).body.getAttribute("scrollHeight", 0);
                int widthsize = (int)(myDoc as HTMLDocumentClass).body.getAttribute("scrollWidth", 0);

                ////Get Screen Height
                int screenHeight = (int)(myDoc as HTMLDocumentClass).body.getAttribute("clientHeight", 0);
                int screenWidth = (int)(myDoc as HTMLDocumentClass).body.getAttribute("clientWidth", 0);

                IntPtr myIntptr = (IntPtr)m_browser.Handle;

                //寻找IE对象句柄
                IntPtr wbHandle = FindWindowEx(myIntptr, IntPtr.Zero, "Shell Embedding", null);
                wbHandle = FindWindowEx(wbHandle, IntPtr.Zero, "Shell DocObject View", null);
                wbHandle = FindWindowEx(wbHandle, IntPtr.Zero, "Internet Explorer_Server", null);
                IntPtr hwnd = wbHandle;

                Bitmap bm = new Bitmap(screenWidth, screenHeight, System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
                Bitmap bm2 = new Bitmap(widthsize, heightsize, System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
                Graphics g = null;
                Graphics g2 = Graphics.FromImage(bm2);
                //切割用的临时对象
                Bitmap tempbm = null;
                Graphics tempg = null;

                IntPtr hdc;
                Image screenfrag = null;
                Image firstScreenfrag = null;

                #region 拼接
                int brwTop = 0;
                int brwLeft = 0;
                int myPage = 0;

                //Get Screen Height (for bottom up screen drawing)
                while ((myPage * screenHeight) < heightsize)
                {
                    (myDoc as HTMLDocumentClass).body.setAttribute("scrollTop", (screenHeight - 5) * myPage, 0);
                    ++myPage;
                }
                //Rollback the page count by one
                --myPage;
                //*************************************************************************
                int myPageWidth = 0;
                //screenWidth+ URLExtraLeft
                while ((myPageWidth * screenWidth) < widthsize)
                {
                    (myDoc as HTMLDocumentClass).body.setAttribute("scrollLeft", (screenWidth - 5) * myPageWidth, 0);
                    brwLeft = (int)(myDoc as HTMLDocumentClass).body.getAttribute("scrollLeft", 0);
                    for (int i = myPage; i >= 0; --i)
                    {
                        //Shoot visible window
                        g = Graphics.FromImage(bm);
                        hdc = g.GetHdc();
                        (myDoc as HTMLDocumentClass).body.setAttribute("scrollTop", (screenHeight - 5) * i, 0);
                        brwTop = (int)(myDoc as HTMLDocumentClass).body.getAttribute("scrollTop", 0);
                        PrintWindow(hwnd, hdc, 0);
                        g.ReleaseHdc(hdc);
                        //g.ReleaseHdc();
                        //g.Flush();
                        screenfrag = Image.FromHbitmap(bm.GetHbitmap());

                        //切除URLExtraLeft、URLExtraHeight长度的webbrowser带来的bug
                        tempbm = new Bitmap(screenWidth - URLExtraLeft, screenHeight - URLExtraHeight, System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
                        tempg = Graphics.FromImage(tempbm);
                        tempg.DrawImage(screenfrag, -URLExtraLeft, -URLExtraHeight);

                        //拼接到g2
                        g2.DrawImage(tempbm, brwLeft + URLExtraLeft, brwTop + URLExtraLeft);

                        //tempg.ReleaseHdc();
                        tempg.Dispose();
                        tempg = null;
                        tempbm.Dispose();
                        tempbm = null;
                        screenfrag.Dispose();
                        screenfrag = null;
                        g.Dispose();
                        g = null;
                       

                    }

                    //g2.ReleaseHdc();
                    
                //*************************************************************************
                    //是否得到第一屏
                    //if (flag)
                    //{
                    //    firstScreenfrag = (Image)tempbm.Clone();
                    //    flag = false;
                    //}

                    ++myPageWidth;
                }
                g2.Dispose();
                int finalWidth = (int)widthsize;
                int finalHeight = (int)heightsize;
                Bitmap finalImage = new Bitmap(finalWidth, finalHeight, System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
                Graphics gFinal = Graphics.FromImage((Image)finalImage);
                gFinal.DrawImage(bm2, 0, 0, finalWidth, finalHeight);

                #endregion

                //Get Time Stamp
                DateTime myTime = DateTime.Now;
                String format = "yyyy_MM_dd_hh_mm_ss";

                //Create Directory to save image to.
                //Directory.CreateDirectory(path);

                //Write Image.
                EncoderParameters eps = new EncoderParameters(1);
                long myQuality = Convert.ToInt64(100);
                eps.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, myQuality);
                ImageCodecInfo ici = GetEncoderInfo("image/jpeg");
                try
                {
                    //保存
                    finalImage.Save(path + "", ici, eps);
                }
                catch
                {
                    //写日志
                    EtlDataProcess.InsertMailErrLog("图片保存失败", "【" + path + "】图片保存失败,可能是因为图片取得错误。");
                }
                finally
                {
                    #region Clean
                    //Clean Up.
                    if(myDoc!=null)
                    myDoc.close();
                    myDoc = null;
                    if(g!=null)
                    g.Dispose();
                    g = null;
                    if(g2!=null)
                    g2.Dispose();
                    g2 = null;
                    if (gFinal != null)
                        gFinal.Dispose();
                    gFinal = null;
                    if(bm!=null)
                    bm.Dispose();
                    bm = null;
                    if(bm2!=null)
                    bm2.Dispose();
                    bm2 = null;
                    if (finalImage != null)
                        finalImage.Dispose();
                    finalImage = null;
                    if(tempbm!=null)
                    tempbm.Dispose();
                    tempbm = null;
                    if (tempg != null)
                    tempg.Dispose();
                    tempg = null;
                    screenfrag = null;
                    #endregion
                }
               

                //保存第一屏
                //if (firstScreen)
                //{
                //    firstScreenfrag.Save(path + @"\Img_FirstScreen_" + myTime.ToString(format) + ".jpg", ici, eps);
                //    firstScreenfrag.Dispose();
                //}

                //Process.Start("explorer.exe", path);

               
            }
        }

starssn 2015-02-04
  • 打赏
  • 举报
回复
bmp是在finally中释放的
starssn 2015-02-04
  • 打赏
  • 举报
回复
是这个过程,最后保存图片用的

Graphics g2 = Graphics.FromImage(bm2);

 int finalWidth = (int)widthsize;
                int finalHeight = (int)heightsize;
                Bitmap finalImage = new Bitmap(finalWidth, finalHeight, System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
                Graphics gFinal = Graphics.FromImage((Image)finalImage);
                gFinal.DrawImage(bm2, 0, 0, finalWidth, finalHeight);

finalImage.Save(path + "", ici, eps);

於黾 2015-02-04
  • 打赏
  • 举报
回复
g2.DrawImage,你最终把图像画到哪里去了? g2不过是画图用的工具,它本身不是图像 图像对象呢(比如Image还是bmp)?释放了吗
starssn 2015-02-04
  • 打赏
  • 举报
回复
引用 10 楼 Z65443344 的回复:
PrintWindow(hwnd, hdc, 0);里又干啥了
拷贝当前窗口用的,内存泄露不在这里啊。郁闷,我只要把g2.DrawImage() 注释掉,一切就都正常了。
Justin-Liu 2015-02-04
  • 打赏
  • 举报
回复
啊 看差大括号了 你找找调用的方法中,有没有new出来对象的,那种也释放掉
本拉灯 2015-02-04
  • 打赏
  • 举报
回复
在循环里加这个试试吧 GC.Collect(); 看看会不会下来,
Justin-Liu 2015-02-04
  • 打赏
  • 举报
回复
你把Dispose放循环里啊亲。。。
starssn 2015-02-04
  • 打赏
  • 举报
回复
你说这可怎么办呢,难道真的没办法吗,因为此方法的使用频率高,一秒钟1.5次左右,怎么能让它来得及释放呢
於黾 2015-02-04
  • 打赏
  • 举报
回复
PrintWindow(hwnd, hdc, 0);里又干啥了
於黾 2015-02-04
  • 打赏
  • 举报
回复
你一张图片大小有10个G? 还是说这个函数你反复执行了许多次之后,内存才达到14G的?
加载更多回复(8)

110,499

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧