首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

C#不断调用浏览器截图函数导致内存溢出有关问题

2012-10-12 
C#不断调用浏览器截图函数导致内存溢出问题?大家好,我用C#写了一函数如下,大致功能是用来截取浏览器上的图

C#不断调用浏览器截图函数导致内存溢出问题?
大家好,我用C#写了一函数如下,大致功能是用来截取浏览器上的图片当我不断调用这个函数几千次的时候,我发现我2G的内存都不够用,会出现内存溢出的现象,不知道这个函数中是哪个地方造成内存泄露的呢?向各位高手请教一下这函数中有哪些地方没有释放好资源呢?
 public Image GetPageImage(string url)//函数中的Browser是.NET控件WebBrowser
  {
  //连接成功
  bool flag = firstScreen;
  //m_browser.ScriptErrorsSuppressed = true;
  Browser.Navigate(url);
  //浏览器Dom载入完毕
  while (Browser.ReadyState != WebBrowserReadyState.Complete)
  {
  Application.DoEvents();

  }
  mshtml.IHTMLDocument2 myDoc = (mshtml.IHTMLDocument2)Browser.Document.DomDocument;
  HTMLDocumentClass myDocClass = (HTMLDocumentClass)myDoc;
  //处理由于webbrowser上、左边框阴影带来的拼接bug
  int URLExtraHeight = 3;
  int URLExtraLeft = 3;

  myDocClass.documentElement.setAttribute("scroll", "yes", 0);

  //document完整高度
  int heightsize = (int)myDocClass.documentElement.getAttribute("scrollHeight", 0);
  int widthsize = (int)myDocClass.documentElement.getAttribute("scrollWidth", 0);

  ////Get Screen Height
  int screenHeight = (int)myDocClass.documentElement.getAttribute("clientHeight", 0);
  int screenWidth = (int)myDocClass.documentElement.getAttribute("clientWidth", 0);

  IntPtr myIntptr = (IntPtr)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.Format32bppPArgb);
  Bitmap bm2 = new Bitmap(widthsize, heightsize, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
  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;

  //获取屏幕高度
  while ((myPage * screenHeight) < heightsize)
  {
  myDocClass.documentElement.setAttribute("scrollTop", (screenHeight - 5) * myPage, 0);
  ++myPage;
  }
  //从后面的屏幕一直到前面
  --myPage;

  int myPageWidth = 0;
  //screenWidth+ URLExtraLeft
  while ((myPageWidth * screenWidth) < widthsize)
  {
  myDocClass.documentElement.setAttribute("scrollLeft", (screenWidth - 5) * myPageWidth, 0);
  brwLeft = (int)myDocClass.documentElement.getAttribute("scrollLeft", 0);
  for (int i = myPage; i >= 0; --i)
  {
  //截下可见窗体
  g = Graphics.FromImage(bm);
  hdc = g.GetHdc();
  myDocClass.documentElement.setAttribute("scrollTop", (screenHeight - 5) * i, 0);


  brwTop = (int)myDocClass.documentElement.getAttribute("scrollTop", 0);
  PrintWindow(hwnd, hdc, 0);
  g.ReleaseHdc(hdc);
  g.Flush();
  screenfrag = Image.FromHbitmap(bm.GetHbitmap());

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

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

  }

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

  ++myPageWidth;
  }

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

  #endregion
  //释放所有Graphics对象,这很重要
  g.Dispose();
  g2.Dispose();
  tempg.Dispose();
  gFinal.Dispose();
  myDoc = null;
  if (bm != null) bm.Dispose();
  if (bm2 != null) bm2.Dispose();
  if (tempbm != null) tempbm.Dispose();
  if (screenfrag != null) screenfrag.Dispose();
  if (firstScreenfrag != null) firstScreenfrag.Dispose();
  return finalImage;
  }

[解决办法]
System.disposeXML()-------仅对XML fp10.1有效
BitmapData.dispose()
Loader.unloadAndStop()----声音动画全能卸
System.gc()----------只适用于调试版
在不就用 SetProcessWorkingSetSize 不过这个会频繁的进行硬盘和内在交互,不见得能达到你理想的程度.
在就是参考一下:
Win32 API资源分配释放速查

热点排行