System.Drawing 参数无效
System.Drawing Parameter is not valid
我目前正在使用 AForge dll 在实时取景的图片框上渲染视频。我确实有一个视频帧功能,可以将当前的图片框帧 WriteFrame 或 Screenshot 为 JPG。
但是我遇到了一个问题,有时候程序会提示Parameter is not valid or Object is being used elsewhere的错误。我确实尝试找到解决方案来解决它,我很确定我确实处理了图像和克隆图像,但问题仍然存在。
你能帮我解决我的程序做错了什么吗?
void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
//your code using bmp object
if (D1Pic.BackColor == Color.Green)
{
video = (Bitmap)eventArgs.Frame.Clone();
if (livePreview.Image != null)
{
//Dispose the resources
this.Invoke(new MethodInvoker(delegate() { livePreview.Image.Dispose(); }));
}
livePreview.Image = (Bitmap)eventArgs.Frame.Clone();
imgclone = (Image)livePreview.Image.Clone();
FileWriter.WriteVideoFrame(video);
}
else
{
video = (Bitmap)eventArgs.Frame.Clone();
if (livePreview.Image != null)
{
//Dispose the resources
this.Invoke(new MethodInvoker(delegate() { livePreview.Image.Dispose(); }));
this.Invoke(new MethodInvoker(delegate() { video.Dispose(); }));
}
livePreview.Image = (Bitmap)eventArgs.Frame.Clone();
imgclone = (Image)livePreview.Image.Clone();
}
video.Dispose();
livePreview.Refresh();
这里是堆栈跟踪错误:
{"Parameter is not valid."}
at System.Drawing.Image.get_Width()
at System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMode mode)
at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
更新代码:
var newFrame = (Bitmap)eventArgs.Frame.Clone();
this.Invoke(new MethodInvoker(delegate()
{
if (livePreview.Image != null)
{
livePreview.Image.Dispose();
}
livePreview.Image = newFrame;
}));
imgclone = (Bitmap)eventArgs.Frame.Clone();
//Write frame into video
if (D1Pic.BackColor == Color.Green)
{
video = (Bitmap)eventArgs.Frame.Clone();
FileWriter.WriteVideoFrame(video);
}
您正在 UI 线程中调用 livePreview.Image.Dispose()
,但之后您没有将 livePreview.Image
设置为 null。
因此,在您处置 livePreview.Image
和为其分配新图像的时间之间,livePreview.Image
指向已处置的对象。
所以我认为您的 picturebox 偶尔会尝试在这段时间内自行绘制,但在尝试访问其(处置的)图像时会失败 属性。
解决方案是:
if (livePreview.Image != null)
{
//Dispose the resources
this.Invoke(new MethodInvoker(delegate() {
livePreview.Image.Dispose();
livePreview.Image = null;
}));
}
或者更好的是,在同一步骤中分配新图像:
var newFrame = (Bitmap)eventArgs.Frame.Clone();
this.Invoke(new MethodInvoker(delegate() {
if (livePreview.Image != null)
{
livePreview.Image.Dispose();
}
livePreview.Image = newFrame;
}));
一般来说,您需要了解各种 Bitmap 对象的情况。任何保留对已处置位图的引用的内容都会有问题。
我目前正在使用 AForge dll 在实时取景的图片框上渲染视频。我确实有一个视频帧功能,可以将当前的图片框帧 WriteFrame 或 Screenshot 为 JPG。
但是我遇到了一个问题,有时候程序会提示Parameter is not valid or Object is being used elsewhere的错误。我确实尝试找到解决方案来解决它,我很确定我确实处理了图像和克隆图像,但问题仍然存在。
你能帮我解决我的程序做错了什么吗?
void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
//your code using bmp object
if (D1Pic.BackColor == Color.Green)
{
video = (Bitmap)eventArgs.Frame.Clone();
if (livePreview.Image != null)
{
//Dispose the resources
this.Invoke(new MethodInvoker(delegate() { livePreview.Image.Dispose(); }));
}
livePreview.Image = (Bitmap)eventArgs.Frame.Clone();
imgclone = (Image)livePreview.Image.Clone();
FileWriter.WriteVideoFrame(video);
}
else
{
video = (Bitmap)eventArgs.Frame.Clone();
if (livePreview.Image != null)
{
//Dispose the resources
this.Invoke(new MethodInvoker(delegate() { livePreview.Image.Dispose(); }));
this.Invoke(new MethodInvoker(delegate() { video.Dispose(); }));
}
livePreview.Image = (Bitmap)eventArgs.Frame.Clone();
imgclone = (Image)livePreview.Image.Clone();
}
video.Dispose();
livePreview.Refresh();
这里是堆栈跟踪错误:
{"Parameter is not valid."}
at System.Drawing.Image.get_Width()
at System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMode mode)
at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
更新代码:
var newFrame = (Bitmap)eventArgs.Frame.Clone();
this.Invoke(new MethodInvoker(delegate()
{
if (livePreview.Image != null)
{
livePreview.Image.Dispose();
}
livePreview.Image = newFrame;
}));
imgclone = (Bitmap)eventArgs.Frame.Clone();
//Write frame into video
if (D1Pic.BackColor == Color.Green)
{
video = (Bitmap)eventArgs.Frame.Clone();
FileWriter.WriteVideoFrame(video);
}
您正在 UI 线程中调用 livePreview.Image.Dispose()
,但之后您没有将 livePreview.Image
设置为 null。
因此,在您处置 livePreview.Image
和为其分配新图像的时间之间,livePreview.Image
指向已处置的对象。
所以我认为您的 picturebox 偶尔会尝试在这段时间内自行绘制,但在尝试访问其(处置的)图像时会失败 属性。
解决方案是:
if (livePreview.Image != null)
{
//Dispose the resources
this.Invoke(new MethodInvoker(delegate() {
livePreview.Image.Dispose();
livePreview.Image = null;
}));
}
或者更好的是,在同一步骤中分配新图像:
var newFrame = (Bitmap)eventArgs.Frame.Clone();
this.Invoke(new MethodInvoker(delegate() {
if (livePreview.Image != null)
{
livePreview.Image.Dispose();
}
livePreview.Image = newFrame;
}));
一般来说,您需要了解各种 Bitmap 对象的情况。任何保留对已处置位图的引用的内容都会有问题。