c# - Why i'm getting OutOfMemoryException even if i release/dispose the Bitmap? -
i have class using code take screenshots:
using system; using system.runtime.interopservices; using system.drawing; using system.drawing.imaging; namespace windowsformsapplication1 { /// <summary> /// provides functions capture entire screen, or particular window, , save file. /// </summary> public class screencapture { /// <summary> /// creates image object containing screen shot of entire desktop /// </summary> /// <returns></returns> public image capturescreen() { homecoming capturewindow(user32.getdesktopwindow()); } /// <summary> /// creates image object containing screen shot of specific window /// </summary> /// <param name="handle">the handle window. (in windows forms, obtained handle property)</param> /// <returns></returns> public image capturewindow(intptr handle) { // te hdc of target window intptr hdcsrc = user32.getwindowdc(handle); // size user32.rect windowrect = new user32.rect(); user32.getwindowrect(handle, ref windowrect); int width = windowrect.right - windowrect.left; int height = windowrect.bottom - windowrect.top; // create device context can re-create intptr hdcdest = gdi32.createcompatibledc(hdcsrc); // create bitmap can re-create to, // using getdevicecaps width/height intptr hbitmap = gdi32.createcompatiblebitmap(hdcsrc, width, height); // select bitmap object intptr hold = gdi32.selectobject(hdcdest, hbitmap); // bitblt on gdi32.bitblt(hdcdest, 0, 0, width, height, hdcsrc, 0, 0, gdi32.srccopy); // restore selection gdi32.selectobject(hdcdest, hold); // clean gdi32.deletedc(hdcdest); user32.releasedc(handle, hdcsrc); // .net image object image img = image.fromhbitmap(hbitmap); // free bitmap object gdi32.deleteobject(hbitmap); homecoming img; } /// <summary> /// captures screen shot of specific window, , saves file /// </summary> /// <param name="handle"></param> /// <param name="filename"></param> /// <param name="format"></param> public void capturewindowtofile(intptr handle, string filename, imageformat format) { using (image img = capturewindow(handle)) { img.save(filename, format); } } /// <summary> /// captures screen shot of entire desktop, , saves file /// </summary> /// <param name="filename"></param> /// <param name="format"></param> public void capturescreentofile(string filename, imageformat format) { using (image img = capturescreen()) { img.save(filename, format); } } /// <summary> /// helper class containing gdi32 api functions /// </summary> private class gdi32 { public const int srccopy = 0x00cc0020; // bitblt dwrop parameter [dllimport("gdi32.dll")] public static extern bool bitblt(intptr hobject, int nxdest, int nydest, int nwidth, int nheight, intptr hobjectsource, int nxsrc, int nysrc, int dwrop); [dllimport("gdi32.dll")] public static extern intptr createcompatiblebitmap(intptr hdc, int nwidth, int nheight); [dllimport("gdi32.dll")] public static extern intptr createcompatibledc(intptr hdc); [dllimport("gdi32.dll")] public static extern bool deletedc(intptr hdc); [dllimport("gdi32.dll")] public static extern bool deleteobject(intptr hobject); [dllimport("gdi32.dll")] public static extern intptr selectobject(intptr hdc, intptr hobject); } /// <summary> /// helper class containing user32 api functions /// </summary> private class user32 { [structlayout(layoutkind.sequential)] public struct rect { public int left; public int top; public int right; public int bottom; } [dllimport("user32.dll")] public static extern intptr getdesktopwindow(); [dllimport("user32.dll")] public static extern intptr getwindowdc(intptr hwnd); [dllimport("user32.dll")] public static extern intptr releasedc(intptr hwnd, intptr hdc); [dllimport("user32.dll")] public static extern intptr getwindowrect(intptr hwnd, ref rect rect); } } } then have new class created i'm using avifile create avi film files screenshots in real time:
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; using avifile; using system.drawing; namespace windowsformsapplication1 { class screenshotstoavi { int count = 0; videostream avistream; avimanager avimanager; bitmap bmp; public screenshotstoavi() { avimanager = new avimanager(@"d:\testdata\new.avi", false); } public void createavi(screencapture sc) { bmp = new bitmap(sc.capturescreen()); count++; if (count == 1) { avistream = avimanager.addvideostream(false, 25, bmp); } avistream.addframe(bmp); bmp.dispose(); } public avimanager avim { { homecoming avimanager; } set { avimanager = value; } } } } then in form utilize this:
using system; using system.collections.generic; using system.componentmodel; using system.data; using system.drawing; using system.linq; using system.text; using system.threading.tasks; using system.windows.forms; using system.io; namespace windowsformsapplication1 { public partial class form1 : form { screenshotstoavi screens2avi; int count; screencapture sc; public form1() { initializecomponent(); screens2avi = new screenshotstoavi(); label2.text = "0"; count = 0; sc = new screencapture(); } private void form1_load(object sender, eventargs e) { } private void timer1_tick(object sender, eventargs e) { count++; sc.capturescreen(); screens2avi.createavi(this.sc); label2.text = count.tostring(); } private void button1_click(object sender, eventargs e) { timer1.enabled = true; } private void button2_click(object sender, eventargs e) { timer1.enabled = false; screens2avi.avim.close(); } private void button3_click(object sender, eventargs e) { timer1.enabled = false; string[] filepaths = directory.getfiles(@"c:\temp\screens7\"); foreach (string filepath in filepaths) file.delete(filepath); label2.text = "0"; } } } after programme running min or 2 it's getting screenshotstoavi class , on line throw exception:
bmp = new bitmap(sc.capturescreen()); out of memory
system.outofmemoryexception unhandled hresult=-2147024882 message=out of memory. source=system.drawing stacktrace: @ system.drawing.graphics.checkerrorstatus(int32 status) @ system.drawing.graphics.drawimage(image image, int32 x, int32 y, int32 width, int32 height) @ system.drawing.bitmap..ctor(image original, int32 width, int32 height) @ system.drawing.bitmap..ctor(image original) @ windowsformsapplication1.screenshotstoavi.createavi(screencapture sc) in d:\c-sharp\readwritetomemory\windowsformsapplication1\windowsformsapplication1\screenshotstoavi.cs:line 26 @ windowsformsapplication1.form1.timer1_tick(object sender, eventargs e) in d:\c-sharp\readwritetomemory\windowsformsapplication1\windowsformsapplication1\form1.cs:line 41 @ system.windows.forms.timer.ontick(eventargs e) @ system.windows.forms.timer.timernativewindow.wndproc(message& m) @ system.windows.forms.nativewindow.debuggablecallback(intptr hwnd, int32 msg, intptr wparam, intptr lparam) @ system.windows.forms.unsafenativemethods.dispatchmessagew(msg& msg) @ system.windows.forms.application.componentmanager.system.windows.forms.unsafenativemethods.imsocomponentmanager.fpushmessageloop(intptr dwcomponentid, int32 reason, int32 pvloopdata) @ system.windows.forms.application.threadcontext.runmessageloopinner(int32 reason, applicationcontext context) @ system.windows.forms.application.threadcontext.runmessageloop(int32 reason, applicationcontext context) @ system.windows.forms.application.run(form mainform) @ windowsformsapplication1.program.main() in d:\c-sharp\readwritetomemory\windowsformsapplication1\windowsformsapplication1\program.cs:line 19 @ system.appdomain._nexecuteassembly(runtimeassembly assembly, string[] args) @ system.appdomain.executeassembly(string assemblyfile, evidence assemblysecurity, string[] args) @ microsoft.visualstudio.hostingprocess.hostproc.runusersassembly() @ system.threading.threadhelper.threadstart_context(object state) @ system.threading.executioncontext.runinternal(executioncontext executioncontext, contextcallback callback, object state, boolean preservesyncctx) @ system.threading.executioncontext.run(executioncontext executioncontext, contextcallback callback, object state, boolean preservesyncctx) @ system.threading.executioncontext.run(executioncontext executioncontext, contextcallback callback, object state) @ system.threading.threadhelper.threadstart() innerexception: and 1 time again im disposing bmp time why exception coming ? need dispose else ?
public void createavi(screencapture sc) { bmp = new bitmap(sc.capturescreen()); count++; if (count == 1) { avistream = avimanager.addvideostream(false, 25, bmp); } avistream.addframe(bmp); bmp.dispose(); } bmp = new bitmap(sc.capturescreen());
that's big reddish flag. i'd assume capturescreen() method returns image or bitmap object. create copy of reason. , dispose copy, not dispose original image returned capturescreen().
that won't lastly long.
assuming need re-create (i have no thought why), you'll have write this:
using (var img = sc.capturescreen()) using (var bmp = new bitmap(img)) { // etc.. } there few image objects not bitmap. metafile other flavor, won't 1 screen-shot. try:
using (var bmp = (bitmap)sc.capturescreen()) { // etc.. } look @ vm size of process in task manager verify memory usage reasonably stable , no longer explodes. want see rapidly increase, bounce , downwards programme keeps running. avi encoder resource pig if doesn't stream avi info straight file. may need switch 64-bit code if requires much memory. add together gdi objects column in task manager, reliably tells if still leaking bitmap objects.
c# .net winforms
No comments:
Post a Comment