Picturebox getting big red X but I can't detect or fix it
Solution 1
In the end, I wrapped EVERYTHING in in the Handle_New_Frame in an invoke. It completely removed the big red X issue, permanently. >_>
private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
this.Invoke((MethodInvoker)delegate
{
try
{
if (bitmap != null)
{
bitmap.Dispose(); //Without this, memory goes nuts
}
bitmap = new Bitmap(eventArgs.Frame);
}
catch { }
//Draw some stuff on the images
bitmap = AdjustBrightness(bitmap, brightnessMeter);
bitmap = ApplyContrast(contrastMeter, bitmap);
bitmap = Draw_Top_Line(bitmap);
bitmap = Draw_Bottom_Line(bitmap);
//Set the image into the picturebox
this.Invoke((MethodInvoker)delegate
{
videoPictureBox1.Image = bitmap;
frameRate++; //Keep track of the frame rate
});
GC.Collect(); //Without this, memory goes nuts
});
}
Solution 2
Shawn Hargreaves has an excellent, concise writeup of the "big red X of doom". I found it very helpful in the general case of dealing with WinForm components suddenly showing the red "X".
In summary:
- This is caused by a control throwing an exception out of the
OnPaint
event. - Once it is thrown, that control will continue to show the red X and skip firing
OnPaint.
- To debug, set the debugger to catch Common Language Runtime Exceptions, and then do whatever you normally do to get the red X. The debugger will stop right where it is happening, allowing you to investigate and hopefully figure out a way to prevent it.
Solution 3
try using the clone in places where you use the bitmap. Ex:
videoPictureBox1.Image = (Bitmap)bitmap.Clone();
C Smith
Updated on June 14, 2022Comments
-
C Smith almost 2 years
I am currently working with AForge, and have an on new frame event that posts the frame, as a bitmap, into a picturebox. 90% of the time it works great... UNLESS I fiddle with something on the winform. Changing a combo box, moving the window, or anything like that risks causing the Picturebox to switch from the video to a big red X. Code sample below:
private void connectButton_Click(object sender, EventArgs e) { try { cam = new VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString); cam.NewFrame -= Handle_New_Frame; //Just to avoid the possibility of a second event handler being put on cam.NewFrame += new AForge.Video.NewFrameEventHandler(Handle_New_Frame); cam.Start(); } catch { MessageBox.Show("An error has occured with connecting to the specified webcam. The application will now close!"); Application.Exit(); } } private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs) { try { if (bitmap != null) bitmap.Dispose(); //Without this, memory goes nuts bitmap = new Bitmap(eventArgs.Frame); } catch { } //Draw some stuff on the images bitmap = AdjustBrightness(bitmap, brightnessMeter); bitmap = ApplyContrast(contrastMeter, bitmap); bitmap = Draw_Top_Line(bitmap); bitmap = Draw_Bottom_Line(bitmap); //Set the image into the picturebox this.Invoke((MethodInvoker)delegate { videoPictureBox1.Image = bitmap; frameRate++; //Keep track of the frame rate }); GC.Collect(); //Without this, memory goes nuts this.Invoke((MethodInvoker)delegate { videoPictureBox1.Refresh(); //NOT NECESSARY. JUST TRYING TO FIX THE BIG RED X! }); if (videoPictureBox1.Image == videoPictureBox1.ErrorImage) { cam.Stop(); //ALSO NOT NECESSARY> AGAIN, JUST TRYING TO FIX THE BIG RED X! cam.Start(); } }
I put a break on the if (videoPictureBox1.Image == videoPictureBox1.ErrorImage) and it is evaluating to false, even when the big red X is up, because the image is actually being set to the bitmap. So cam.Stop() and cam.Start() never run (not sure if that would even help, but I figured I would give it a try).
videoPictureBox1.Refresh() is running every time, but again- it's not making a difference. Still have the big red X.
As I said before: if I start the video and touch nothing, the big red X will never happen. But the moment I start changing combo boxes, or dragging the form itself around, the chance of the big red X goes up exponentially. Sometimes I can flip through the combo box 10-12 times before it happens, other times it happens the second I click the combobox. :-\
Can anyone explain what is happening here and perhaps offer a suggestion on the best method to go about fixing it? I'm still very new to threading, so I've been struggling to wrap my head around exactly what is happening here and the best way to fix the issue! Any nudges in the right direction would be a huge help!
-
James Barrass about 11 yearsI think I'd probably just not use a picture box. Use a panel instead and draw the bitmap in the paint event of the panel. Forcing a refresh with invalidate.
-
TheKingDave about 11 yearsHave you had a look at the eventArgs.Frame during the big red X senario? Also I would put a messagebox under that exception just in case that is where the error occurs.
-
C Smith about 11 yearsAlright, I'll give that a try really quick! An additional note: I went to debug -> exceptions and checked all the "Thrown" checkboxes. Nothing throws when that happens. At all.
-
C Smith about 11 yearsKingDave, I'll give that a try right now as well! Thanks!
-
C Smith about 11 yearsI added a panel changed "videoPictureBox1.Image = bitmap" to "panel3.BackGroundImage = bitmap; panel3.Invalidate();". I got the big red X again when moving the form around :( I also added a message in that catch- it was never called! It's a confusing little bug I've introduced! If only fixing it was as easy as creating it lol!
-
C Smith about 11 yearsI checked the contents of eventArgs.Frame while the Red X is up, and it is the image that it is supposed to be pulling (or at least appears to be. It's of the proper height/width/resolution).
-
-
Hans about 11 yearsThis could also lead to a race condition or am I wrong? If a redraw happens between disposing the bitmap and cloning the bitmap then the big red X will show up.
-
Rafael Souza about 11 years@Hans yes, try using the bitmap before dispose()
-
Xan-Kun Clark-Davis about 7 yearsI ran into the exact same thing and also tried to figure out what's going on, to no avail. I guess it some single-thread policy, but I as I could get no exceptions or errormessages whatsoever, I went with your approach and now it works.
-
Xan-Kun Clark-Davis about 7 years@Hans could you please check the code in my answer? I tried to generate such a race condition but was not able to.
-
Xan-Kun Clark-Davis about 7 yearsBTW: I abandoned this approach for obvious reasons quite quickly :-)
-
elle0087 over 6 yearshi, i used it, but when i try to close videoSource it doesn t stop and stay wait to release the resource...have you got the same problem?
-
elle0087 over 6 yearshi, i used it, but when i try to close videoSource it doesn t stop and stay wait to release the resource...have you got the same problem?
-
Micah Epps about 5 yearsRegarding your comment on GC.Collect(). Bitmap's inheritance chain implements IDisposable. The GC issue is likely due you missing calling Dispose. Try a using block or manually call bitmap.Dispose().
-
Tobias Knauss over 4 yearsLink broken. Updated Link: shawnhargreaves.com/blog/…
-
Mark Meuer over 4 years@TobiasKnauss Thank you! I've updated the link in the answer.