【问题标题】:WinForm Control BeginInvoke/Invoke IssueWinForm 控件 BeginInvoke/Invoke 问题
【发布时间】:2014-01-22 08:41:17
【问题描述】:

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

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

委托功能:

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。 显然,这与参数的垃圾收集有关,但我根本无法弄清楚这一点。

非常感谢任何帮助。

谢谢

【问题讨论】:

  • 不,不是垃圾收集。更像是b 是从像相机这样的图像源创建的,由回调提供给您。 unmanaged 像素数据在回调返回后失效。不公开图片来源就无法正确回答。

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


【解决方案1】:

在我看来,首先调用DrawCVImageShow 的任何东西都是DisposingDrawCVImageShow 返回后立即出现的位图。

如果是这样的话,有几种可能:

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

【讨论】:

    猜你喜欢
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    相关资源
    最近更新 更多