我的图像处理全部是用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;
}
}
}
由于 BitmapSource 是在 UI 线程以外的线程中创建的,因此在分配给 Image 元素的 Source 属性之前必须将其冻结:
private void Cli_ImageUpdated(object sender, ImageUpdateEventArgs e)
{
e.img.Freeze();
Dispatcher.Invoke(() => MyImageControl.Source = e.img);
}
详情请参阅Freezable.Freeze和Freezable.IsFrozen中的备注部分。