Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 保存屏幕截图图像时出现内存不足异常,即使每次处理时也是如此_C#_.net_Winforms - Fatal编程技术网

C# 保存屏幕截图图像时出现内存不足异常,即使每次处理时也是如此

C# 保存屏幕截图图像时出现内存不足异常,即使每次处理时也是如此,c#,.net,winforms,C#,.net,Winforms,我有一个保存桌面截图的类 #region Class Imports using System; using System.Drawing; using System.IO; using System.Windows.Forms; using System.ComponentModel; #endregion namespace Manager { public class ScreenShot { #region Global Variables priv

我有一个保存桌面截图的类

#region Class Imports 
using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.ComponentModel;
#endregion

namespace Manager
{
    public class ScreenShot
    {

    #region Global Variables
    private Bitmap _screenShot;
    protected static IntPtr newBMP;
    #endregion

    #region Constants
    public const int SRCCOPY = 13369376;
    public const int SCREEN_X = 0;
    public const int SCREEN_Y = 1;
    #endregion

    #region Class Properties
    [Description("Gets the screenshot image")]
    public Bitmap ScreenImage
    {
        get { return _screenShot; }
    }
    #endregion

    #region Constructor

    [Description("Empty constructor, instantiating _screenShot to nothing")]
    public ScreenShot()
    {
        _screenShot = null;
    }              
    #endregion

    #region Methods

    [Description("Creates an image of the current desktop")]
    public Bitmap GetScreen()
    {
        int xLoc;
        int yLoc;
        IntPtr dsk;
        IntPtr mem;
        Bitmap currentView;

        //get the handle of the desktop DC
        dsk = Win32API.GetDC(Win32API.GetDesktopWindow());

        //create memory DC
        mem = Win32API.CreateCompatibleDC(dsk);

        //get the X coordinates of the screen
        xLoc = Win32API.GetSystemMetrics(SCREEN_X);

        //get the Y coordinates of screen.
        yLoc = Win32API.GetSystemMetrics(SCREEN_Y);

        //create a compatible image the size of the desktop
        newBMP = Win32API.CreateCompatibleBitmap(dsk, xLoc, yLoc);

        //check against IntPtr (cant check IntPtr values against a null value)
        if (newBMP != IntPtr.Zero)
        {
            //select the image in memory
            IntPtr oldBmp = (IntPtr)Win32API.SelectObject(mem, newBMP);
            //copy the new bitmap into memory
            Win32API.BitBlt(mem, 0, 0, xLoc, yLoc, dsk, 0, 0, SRCCOPY);
            //select the old bitmap into memory
            Win32API.SelectObject(mem, oldBmp);
            //delete the memoryDC since we're through with it
            Win32API.DeleteDC(mem);
            //release dskTopDC to free up the resources
            Win32API.ReleaseDC(Win32API.GetDesktopWindow(), dsk);
            //create out BitMap
            currentView = Image.FromHbitmap(newBMP);
            //return the image
            return currentView;
        }
        else  //null value returned
        {
            return null;
        }    
    }
    #endregion

    public void GetScreenShot(string folder, string name)
    {
        _screenShot = new Bitmap(GetScreen());
        string ingName = folder + name + Elgato_Video_Capture.counter.ToString("D6") + ".bmp";
        _screenShot.Save(ingName);
        _screenShot.Dispose();
    }
    }

}
在form1中与计时器一起使用:

private void button1_Click(object sender, EventArgs e)
{
    timer1.Start();
}
如果发生以下情况:

ScreenShot shot = new ScreenShot();
public static int counter = 0;
private void timer1_Tick(object sender, EventArgs e)
{
    counter++;
    shot.GetScreenShot(@"e:\screenshots\", "screenshot");
    if (counter == 1200)
    {
        timer1.Stop();
        ScreenShotsPlayer ssp = new ScreenShotsPlayer();
        ssp.Show();
    }
}
例外情况出现在行底部的新类中:

_screenShot = new Bitmap(GetScreen());
保存图像编号screenshot000147.bmp后,这种情况一直发生

System.OutOfMemoryException occurred
  HResult=-2147024882
  Message=Out of memory.
  Source=System.Drawing
  StackTrace:
       at System.Drawing.Graphics.CheckErrorStatus(Int32 status)
       at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y, Int32 width, Int32 height)
       at System.Drawing.Bitmap..ctor(Image original, Int32 width, Int32 height)
       at System.Drawing.Bitmap..ctor(Image original)
       at Youtube_Manager.ScreenShot.GetScreenShot(String folder, String name) in d:\C-Sharp\Manager\Manager\Manager\ScreenShot.cs:line 105
  InnerException: 
第105行是:
\u屏幕截图=新位图(GetScreen())

每次保存后,我都会处理_屏幕截图变量。 也许form1中的计时器太快了?计时器间隔设置为100ms。

根据源进行复制;因此,原始的
newBMP
将“丢失在非托管内存中”,因为它从未被释放

FromHbitmap方法复制GDI位图;因此,您可以在创建新图像后立即释放传入的GDI位图(使用GDI DeleteObject方法)


当变量没有全局用途时,将其保留为局部:在public void getScreenShot()中声明位图。您的问题的答案很可能在这里:我认为调用
GC.Collect()
可以解决问题。@NorbertvanNobelen发布的代码已经执行了
Dispose
。调用Dispose不会强制收集内存@user2864740@dotctor
Dispose
将释放系统/非托管资源。只有当没有显式的Dispose(这违反了编码约定),但托管对象不再具有强可访问性时,才需要GC.Collect。