C# Dispose function giving an error

北慕城南 提交于 2019-12-24 20:13:22

问题


I am trying to take screenshot for every 10 miliseconds and set them as a Picturebox.image with Timer. For few seconds program runs perfectly but after few seconds program is crashing. I tried to use Dispose() Function in the end of the code to clear the memory but Dispose Function also gives an error. (increasing interval of timer doesn't worked)

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;

namespace gameBot
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        public Bitmap screenshot;
        Graphics GFX;
        private void button1_Click(object sender, EventArgs e)
        {
            timer1.enabled = true;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            takescreenshot();
        }
        private void takescreenshot()
        {

            screenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, 
            Screen.PrimaryScreen.Bounds.Height);
            GFX = Graphics.FromImage(screenshot);
            GFX.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size);
            pictureBox1.Image = screenshot;
            screenshot.Dispose();              
        }           
    }
}

The error is

"An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll

Additional information: Parameter is not valid."

Also program is using too much RAM before crashing (Maybe it's crashing because of out of memory exception?) As you can see in here


回答1:


See Graphics.FromImage():

You should always call the Dispose method to release the Graphics and related resources created by the FromImage method.

Also, there's no need to keep that Graphics at Class level.

With that in mind, all you need is:

public Bitmap screenshot;

private void takescreenshot()
{
    if (screenshot != null)
    {
        screenshot.Dispose();
    }

    screenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
    using (Graphics GFX = Graphics.FromImage(screenshot))
    {
        GFX.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size);
    }
    pictureBox1.Image = screenshot;
}



回答2:


I would suggest changing:

pictureBox1.Image = screenshot;
screenshot.Dispose();

to:

var oldScreenshot = pictureBox1.Image;
pictureBox1.Image = screenshot;
GFX.Dispose();
if (oldScreenshot != null)
    oldScreenshot.Dispose;

to ensure that the old screenshot is disposed whenever you assign a new one.




回答3:


1) Actually your first problem "Parameter is not valid." is beacause youre disposing screenshot object. If you will try to run your takescreenshot() method only once - you will get this error. I assume that happens because you set object "screenshot" to PictureBox1.Image and than immediately dispose it. Thats logical! PictureBox can`t render disposed object.

2) Try to modify your code on button handler like that:

    private Object thisLock = new Object();
    private void button1_Click(object sender, EventArgs e)
    {
        Thread thr = new Thread(() =>
        {
            while (true)
            {pictureBox1.Invoke((Action)(() =>
                    {
                        screenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
                            Screen.PrimaryScreen.Bounds.Height);
                        GFX = Graphics.FromImage(screenshot);
                        GFX.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0,
                            Screen.PrimaryScreen.Bounds.Size);
                        pictureBox1.Image = screenshot;
                    }));
                }
                Thread.Sleep(10);
        });
        thr.Start();
    }

Works fine! The best way is to get event when picturebox finished rendering, But I didn`t find anything about this.



来源:https://stackoverflow.com/questions/45128806/c-sharp-dispose-function-giving-an-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!