简体   繁体   English

System.Drawing参数无效

[英]System.Drawing Parameter is not valid

I'm currently using AForge dll to render the video on the picture box for the live view. 我目前正在使用AForge dll在图片框中渲染实时视图的视频。 I do have a video frame function to whether WriteFrame or Screenshot the current picturebox frame as a JPG. 我确实有一个视频帧功能,无论是WriteFrame还是将当前的图片框框架截图为JPG。

But i met a problem when sometime the program will prompt out an error of Parameter is not valid or Object is been used elsewhere. 但是我遇到了一个问题,有时程序会提示参数无效或者其他地方使用了对象的错误。 I did try to find solution to solve it and i pretty sure i did dispose on the image and the clone image, but the problem still exist. 我确实试图找到解决方案来解决它,我很确定我已经处理了图像和克隆图像,但问题仍然存在。

Could you assist me on what i had done wrong with my program? 你能帮助我解决我的计划错误吗?

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

Here are the stack trace error : 以下是堆栈跟踪错误:

{"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)

UPDATED CODE : 更新的代码:

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

You are calling livePreview.Image.Dispose() in the UI thread, but you're not setting livePreview.Image to null afterwards. 你在UI线程中调用livePreview.Image.Dispose() ,但之后你没有将livePreview.Image设置为null。

So between the time that you dispose livePreview.Image and the time that you assign a new image to it, livePreview.Image points to a disposed object. 因此,在您处理livePreview.Image的时间和为其分配新图像的时间之间, livePreview.Image指向已处置的对象。

So I think occasionally your picturebox tries to draw itself during this time, and fails when it attempts to access its (disposed) Image property. 因此,我认为偶尔你的图片框试图在这段时间内绘制自己,并在尝试访问其(处置的)Image属性时失败。

The solution would be: 解决方案是:

if (livePreview.Image != null)
{
    //Dispose the resources
    this.Invoke(new MethodInvoker(delegate() { 
        livePreview.Image.Dispose(); 
        livePreview.Image = null;
    }));
}

Or even better, assign the new image in the same step: 或者甚至更好,在同一步骤中分配新图像:

var newFrame = (Bitmap)eventArgs.Frame.Clone();
this.Invoke(new MethodInvoker(delegate() { 
    if (livePreview.Image != null)
    {
        livePreview.Image.Dispose(); 
    }
    livePreview.Image = newFrame;
}));

In general, you need to understand what's happening with your various Bitmap objects. 通常,您需要了解各种Bitmap对象所发生的情况。 Anything that keeps a reference to a Bitmap that has been disposed will be a problem. 任何保留对已经处置的位图的引用都将是一个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM