【问题标题】:System.Drawing Parameter is not validSystem.Drawing 参数无效
【发布时间】:2016-05-17 06:04:01
【问题描述】:

我目前正在使用 AForge dll 来渲染图片框上的视频以进行实时取景。我确实有一个视频帧功能,无论是 WriteFrame 还是 Screenshot 将当前的图片框帧作为 JPG。

但我遇到了一个问题,有时程序会提示错误参数无效或对象已在其他地方使用。我确实试图找到解决方案来解决它,我很确定我确实对图像和克隆图像进行了处理,但问题仍然存在。

你能帮我解决我的程序做错了什么吗?

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);
                }

【问题讨论】:

  • 错误出现在哪一行?
  • @JeremyThompson livePreview.Refresh()
  • 改用livePreview.Invalidate()
  • @JeremyThompson 我确实尝试过使用 livePreview,Invalidate()。一段时间后,程序仍然向我抛出“参数无效”异常。
  • 发布整个异常详情,并指出是哪一行抛出的。

标签: c# .net aforge


【解决方案1】:

您在 UI 线程中调用 livePreview.Image.Dispose(),但之后您没有将 livePreview.Image 设置为 null。

因此,在您处置 livePreview.Image 和为其分配新图像的时间之间,livePreview.Image 指向已处置的对象。

所以我认为您的图片框有时会在此期间尝试绘制自己,并在尝试访问其(已处置的)图像属性时失败。

解决办法是:

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;
}));

一般来说,您需要了解各种位图对象的情况。任何保留对已释放位图的引用的东西都是问题。

【讨论】:

  • 视频也一样吗?我的意思是用于视频录制的 FileWriter
  • 我看不出那部分有问题,据我所知,这一切都发生在同一个线程上。
  • 请查看我的更新代码,我已经对我的代码进行了更改。代码可以吗?
  • 我正在使用 imgclone 保存部分。你想看吗?我将在 imgClone.Save 函数之后处理它。那会不会导致参数无效?目前我正在运行程序,看看会不会出现问题
  • 它不应该导致 ObjectDisposedException,因为您没有在另一个线程中处理它,所以(希望)在它被处理后您不会访问它。 video 是否也在其他地方使用?我没有在您发布的代码中看到它声明,所以我认为它是一个成员级字段,但您正在代码中处理它..
猜你喜欢
  • 2012-12-15
  • 2021-07-12
  • 2023-03-20
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多