I've been writing a program and every time I close my form it throws an exception saying my stack overflowed on the line which closes the background worker...
I have faced this problem for some time now, I've tried googling the problem but I haven't come up with any desired solution yet...
My troubleshooting guesses are as follows :
Here is my code, thanks in advance !
Elements
Picturebox called videobox
Button called btnOpenCamera_Click
Button called btnCloseCamera_Click
Label called backgroundworkerStatus
Variables
Global
Mat videoFrame; VideoCapture video(0);
Private
bool flag_cameraStatus = true; bool flag_backgroundworkerStatus = false;
Functions
private: System::Void MainForm_FormClosing
// this event is triggered when application is closing video.release(); /* Exception is thrown here "System.StackOverflowException" */ backgroundWorker->CancelAsync(); if (backgroundWorker->IsBusy == false) { checkBackgroundworkerStatus(); this->Close(); } else { MessageBox::Show("Backgroundworker not aborted"); e->Cancel = true; }
private: System::Void btnOpenCamera_Click
// this is a button for turning on camera flag_cameraStatus = true; backgroundWorker->RunWorkerAsync();
private: System::Void btnCloseCamera_Click
// this is a button for turning off camera flag_cameraStatus = false; videoBox->Image = nullptr;
int openCamera()
// this is a button for turning off camera if (!video.isOpened()) { MessageBox::Show("Cannot Find Camera!"); return -1; } while (flag_camera) { video >> videoFrame; if (videoFrame.empty()) { break; } /* These lines of code converts Opencv mat to bitmap for picturebox to display */ System::Drawing::Graphics^ graphics = videoBox->CreateGraphics(); System::IntPtr ptr(videoFrame.ptr()); System::Drawing::Bitmap^ b = gcnew System::Drawing::Bitmap(videoFrame.cols, videoFrame.rows, videoFrame.step, System::Drawing::Imaging::PixelFormat::Format24bppRgb, ptr); System::Drawing::RectangleF rect(0, 0, videoBox->Width, videoBox->Height); graphics->DrawImage(b, rect); /* Was wondering if I need these lines of code below */ /* delete graphics; */ if (flag_camera == false) { videoBox->Image = nullptr; return 0; }
void checkBackgroundworkerStatus()
// this function is used to check if backgroundworker is busy // it will identify the status via the backcolor of label backgroundworkerStatus if(backgroundWorker->IsBusy==true) backgroundworkerStatus->BackColor = Color::Green; else backgroundworkerStatus->BackColor = SystemColors::Control;
private: System::Void backgroundWorker_DoWork
// this event is triggered when background worker is working if (backgroundWorker->CancellationPending == false) { checkBackgroundworkerStatus(); openCamera(); } else { this->backgroundWorker->CancelAsync(); }
private: System::Void backgroundWorker_RunWorkerCompleted
// this event is triggered when background worker is done working checkBackgroundworkerStatus();
Some Last Notes...
I did set my
WorkerSupportsCancellation = true
WorkerReportsProgress = true
To solve this problem,add a delay to DoWork
private: System::Void backgroundWorker1_DoWork
using namespace System::Threading
/* your DoWork tasks */
Thread::Sleep(50)
Note
Thread::Sleep counts in milliseconds, you can change to the number you want according to your cameras fps.
My laptop webcam is approx. 15 fps, which is 66.66 ms per frames, the sleep time should be >= this ms/frame but I have no problems running it with a delay of only 50ms.