I am trying to write a multithreaded WinForm in C++/CLI app using VS2012.
I know that only the UI thread can update a control and I have been using delegates and the invoke methods. However, I have run into a memory access issue when using BeginInvoke that I do not see when using Invoke.
Delegate Function:
public: delegate void pictureboxShowDelegate(int tChannelNumber,System::Windows::Forms::PictureBox^,System::Drawing::Bitmap^ colorImage);
Called Function:
void DrawCVImageShow(int tChannelNumber, System::Windows::Forms::PictureBox^ PBox, System::Drawing::Bitmap^ b)
{
if(PBox->InvokeRequired)
{
pictureboxShowDelegate^ d = gcnew pictureboxShowDelegate(this,&MyForm::DrawCVImageShow);
PBox->Invoke(d,tChannelNumber,PBox,b);
}
else
{
System::Drawing::Graphics^ graphics = PBox->CreateGraphics();
System::Drawing::RectangleF rect(0,0,(float)PBox->Width,(float)PBox->Height);
graphics->DrawImage(b,rect);
}
}
If called this way, it works with no problem. If I substitute BeginInvoke for Invoke, I get an AccessViolationException. Clearly, this has to do with the garbage collection of the parameters but I simply can't figure this one out.
Any help greatly appreciated.
Thanks
It sounds to me like whatever is calling
DrawCVImageShow
in the first place is Disposing the bitmap immediately afterDrawCVImageShow
returns.If that's the case, there are a couple possiblities:
DrawCVImageShow
is the one responsible for Disposing the bitmap, not whatever callsDrawCVImageShow
. (Simple solution, though probably not the best from an engineering solution: The thing that created the bitmap should generally be responsible for disposing it, and it makesDrawCVImageShow
a less general method.)DrawCVImageShow
, one that disposes the bitmap (for BeginInvoking), and one that doesn't (the method you have now). This also means you'll have two copies of the bitmap in memory when a BeginInvoke is needed; hopefully these bitmaps are not so large that this is an issue.