C++ Cli 将图像指针传递给 WPF 进行显示

问题描述 投票:0回答:1

我的图像处理全部是用C++进行的。之前使用MFC,现在正在考虑升级到WPF。 WPF 端主要是用户界面,我将图像指针从非托管传递到托管以进行显示。我发现,如果我使用线程循环后端向量,它不会显示任何内容,但如果我将其更改为按钮触发,它将起作用。同样的功能,我不知道发生了什么。

WPF 拥有我的 CppCli 对象,它可以直接调用 c++ / cli 中的任何函数。这里可能出了什么问题。

wpf CS 代码:

private CppCli cli;

public MainWindow() { 
    cli = new CppCli(); 
    cli.ImageUpdated += Cli_ImageUpdated; // delegate and event to call method Cli_ImageUpdated 
    InitializeComponent(); 
}

private void Cli_ImageUpdated(object sender, ImageUpdateEventArgs e) 
{ 
    Dispatcher.Invoke(() =>
    {
        MyImageControl.Source = e.img;
    });
} 

private void LiveToggle_Click(object sender, RoutedEventArgs e) {

    cli.LiveToggle(); 
}

Cpp cli代码:

public ref class ImageUpdateEventArgs : EventArgs { 
    public: BitmapSource^ img;

    ImageUpdateEventArgs(BitmapSource^ bitmap) { 
        img = bitmap;
    } 
};

void CppCli::LiveToggle() { 
    running = !running; 

    if (running) { 
        liveThread = gcnew Thread(gcnew ThreadStart(this, &MathFunctions::UpdateDisplay)); 
        liveThread->IsBackground = true; 
        liveThread->Start();
    }

    //UpdateDisplay() // This works if replace the whole thing above. 
}

void CppCli::UpdateDisplay() { 
    while (running) { // Remove this while loop and it works.

        int stride, rows, cols, bufferSize; 
        stride = cvObj->images[imageIndex].step[0]; 
        rows = cvObj->images[imageIndex].rows; 
        cols = cvObj->images[imageIndex].cols; 
        bufferSize = cvObj->images[imageIndex].total() * cvObj->images[imageIndex].elemSize(); 
        IntPtr ptr(cvObj->images[imageIndex].ptr()); 

        ImageUpdated(this, gcnew ImageUpdateEventArgs(BitmapSource::Create(cols, rows, 96, 96, PixelFormats::Bgra32, nullptr, ptr, bufferSize, stride)));

        Thread::Sleep(100); 
        imageIndex++; 
        if (imageIndex >= cvObj->images.size())
        { 
            imageIndex = 0;
        }
    } 
}
wpf multithreading c++-cli interop
1个回答
0
投票

由于 BitmapSource 是在 UI 线程以外的线程中创建的,因此在分配给 Image 元素的 Source 属性之前必须将其冻结:

private void Cli_ImageUpdated(object sender, ImageUpdateEventArgs e) 
{ 
    e.img.Freeze();
    Dispatcher.Invoke(() => MyImageControl.Source = e.img);
}

详情请参阅Freezable.FreezeFreezable.IsFrozen中的备注部分。

© www.soinside.com 2019 - 2024. All rights reserved.