问题
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
回答1:
It sounds to me like whatever is calling DrawCVImageShow
in the first place is Disposing the bitmap immediately after DrawCVImageShow
returns.
If that's the case, there are a couple possiblities:
- Make it so that
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.) - Make a Clone of the bitmap, and dispose that one after it's been used. This is the more proper solution, in my opinion, but it does make things a little bit more complicated. You now need two versions of
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.
来源:https://stackoverflow.com/questions/20924641/winform-control-begininvoke-invoke-issue