我尝试每隔10毫秒拍摄一次屏幕截图并将其设置为带有Timer的Picturebox.image
。几秒钟程序运行完美,但几秒后程序崩溃。我尝试在代码末尾使用Dispose()
函数来清除内存,但Dispose Function也会出错。 (增加计时器的间隔时间不起作用)
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();
}
}
}
错误是
"未处理的类型' System.ArgumentException'发生在System.Drawing.dll
中
附加信息:参数无效。"
同样程序在崩溃之前使用了太多的RAM(可能是因为内存不足异常导致崩溃?) As you can see in here
答案 0 :(得分:1)
我建议改变:
pictureBox1.Image = screenshot;
screenshot.Dispose();
为:
var oldScreenshot = pictureBox1.Image;
pictureBox1.Image = screenshot;
GFX.Dispose();
if (oldScreenshot != null)
oldScreenshot.Dispose;
确保在分配新屏幕截图时处理旧屏幕截图。
答案 1 :(得分:0)
您应该始终调用Dispose方法来释放Graphics和 FromImage方法创建的相关资源。
此外,没有必要将该图形保持在类级别。
考虑到这一点,您只需要:
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 :(得分:0)
1)实际上你的第一个问题是“参数无效”。因为你正在处理截图对象。 如果您只尝试运行一次takecreenshot()方法 - 您将收到此错误。我认为这是因为您将对象“屏幕截图”设置为PictureBox1.Image而不是立即处理它。多数民众赞成! PictureBox无法呈现处置对象。
2)尝试在按钮处理程序上修改代码:
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();
}
工作正常!最好的方法是在picturebox完成渲染时获取事件,但我没有找到任何关于此的内容。