WinForm控件BeginInvoke / Invoke问题

时间:2014-01-04 18:03:48

标签: multithreading winforms c++-cli invoke begininvoke

我正在尝试使用VS2012在C ++ / CLI应用程序中编写多线程WinForm。

我知道只有UI线程可以更新控件,我一直在使用委托和调用方法。但是,在使用我在使用Invoke时看不到的BeginInvoke时,我遇到了内存访问问题。

代表职能:

public: delegate void pictureboxShowDelegate(int tChannelNumber,System::Windows::Forms::PictureBox^,System::Drawing::Bitmap^ colorImage);

被叫函数:

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

如果以这种方式调用,它没有问题。 如果我用BeginInvoke替换Invoke,我会得到一个AccessViolationException。 显然,这与参数的垃圾收集有关,但我根本无法解决这个问题。

非常感谢任何帮助。

由于

1 个答案:

答案 0 :(得分:0)

在我看来,DrawCVImageShow之后调用DrawCVImageShow的任何内容都是Disposing紧跟DrawCVImageShow之后的位图。

如果是这种情况,有几种可能性:

  • 使DrawCVImageShow负责处理位图,而不是调用DrawCVImageShow。 (简单的解决方案,虽然可能不是工程解决方案中的最佳解决方案:创建位图的东西通常应该负责处理它,并且它使DrawCVImageShow成为一种不那么通用的方法。)
  • 制作位图的Clone,并在使用后对其进行处理。在我看来,这是更合适的解决方案,但它确实使事情变得更复杂一些。您现在需要两个版本的{{1}},一个用于处理位图(用于BeginInvoking),另一个用于处理(现在的方法)。这也意味着当需要BeginInvoke时,你将在内存中有两个位图副本;希望这些位图不是那么大,这是一个问题。