将 WriteableBitmap 线程化到图像控件

Posted

技术标签:

【中文标题】将 WriteableBitmap 线程化到图像控件【英文标题】:Threading WriteableBitmap to Image control 【发布时间】:2021-07-09 13:16:01 【问题描述】:

我在 .NET Core 3.1 平台上使用 OpenGL 在 WPF 中呈现静态图片。上下文最初显示在隐藏的 GLFW 窗口中。然后我使用glReadPixels 读取上下文并将其显示在 UI 上的 Image 控件上,使用下面显示的代码。不使用线程时,代码工作正常。但是,当通过不同的线程调用渲染代码时,不会显示图像。作为中间检查,我创建了using (FileStream... 代码,它读取WriteableBitmap 并将其保存在本地,并且看起来工作正常;这意味着 WriteableBitmap 已正确创建。所以,我想问题是如何将 WriteableBitmap 传输到 Image 控件,这两个控件都是在不同的线程上创建的。 Dispatcher.BeginInvoke 出于某种奇怪的原因无法正常工作。

    byte[] imageBuffer = new byte[imageWidth * imageHeight * 4];
    glReadPixels(0, 0, imageWidth, imageHeight, GL_BGRA, GL_UNSIGNED_BYTE, imageBuffer);
    imageBuffer = ImageReverse(imageBuffer, imageWidth);
    PixelFormat pixelFormat = PixelFormats.Pbgra32;
    int rawStride = (imageWidth * pixelFormat.BitsPerPixel) / 8;
    BitmapSource bitmapSource = BitmapSource.Create(imageWidth, imageHeight, 96, 96, pixelFormat, null, imageBuffer, rawStride);
    WriteableBitmap writeableBitmap = new WriteableBitmap(bitmapSource);

    //This is a check whether the writeableBitmap has been created correctly
    using (FileStream fileStream = new FileStream(@"C:\Temp\Image1.bmp", FileMode.Create))
    
        BmpBitmapEncoder encoder = new BmpBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(writeableBitmap));
        encoder.Save(fileStream);
    

    Action action = new Action(() => 
        _imgSoilProfile.Source = writeableBitmap; 
    );
    _imgSoilProfile.Dispatcher.BeginInvoke(action, DispatcherPriority.Send);

【问题讨论】:

这行得通!谢谢mm8! 【参考方案1】:

在设置ImageSource之前尝试在后台线程上调用w.Freeze()

using (FileStream fileStream = new FileStream(@"C:\Temp\Image1.bmp", FileMode.Create))

    ...

w.Freeze();

Action action = new Action(() => 
    _imgSoilProfile.Source = writeableBitmap; 
);

来自docs:

冻结的 Freezable 也可以跨线程共享,而未冻结的 Freezable 则不能。

【讨论】:

以上是关于将 WriteableBitmap 线程化到图像控件的主要内容,如果未能解决你的问题,请参考以下文章

在UWP 将BitmapImage转换为 WriteableBitmap

在 C# 中为 WindowsPhone 8 调整 WriteableBitmap 的大小

WriteableBitmap 巧学巧用

WPF学习第四十七章 WriteableBitmap类

将静态控件子类化到对话框窗口

WriteableBitmap 只能写入一次吗?