c# - 在后台线程上创建位图会停止渲染线程

标签 c# wpf multithreading graphics

一些背景知识:我正在为声纳记录回放的显示制作动画。声纳记录文件很大(通常为 100 - 600MB),因此根据需要加载片段。它的核心是我们预先索引声纳文件,然后使用内存映射文件根据需要加载数据 block 。然后使用数据创建位图 - 非常简单,因为数据由字节组成,我们只需使用 8 位调色板将它们映射到颜色。

出于性能原因,我们在后台进行所有加载,并在其自己的绘图视觉中渲染每个片段。这工作正常,手动 ScrollView (或跳转到特定位置)提供非常好的性能。

我们遇到的问题 - 这确实是一个小问题,但却是一个非常恼人的问题 - 是我们在更高速度下播放时出现故障。我已经将原因缩小到我们在线程池线程中创建可写位图的那一刻。代码如下:

BitmapPalette bmp = new BitmapPalette(Palette);

WriteableBitmap wb = new WriteableBitmap(segment_bytes.ping_width, segment_bytes.height, 96, 96, System.Windows.Media.PixelFormats.Indexed8, bmp);

Int32Rect update_rect = new Int32Rect(0, 0, segment_bytes.ping_width, segment_bytes.height);
wb.WritePixels(update_rect, segment_bytes.data, segment_bytes.ping_width, 0);

wb.Freeze();

_element.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background,
new Action(delegate()
{
    brush.set_image_brush(wb);
}));

set_image_brush 调用只是设置用于渲染片段(通过 drawRectangle)的画笔的图像源并启动一个简短的不透明度动画。

通过反复试验(注释掉代码位),我确定是 WriteableBitmap 的构造函数导致了每个段的减速/故障,并且在较大的段上更为明显。因此,尽管这一切都发生在线程池线程中,但 WB 的创建发生在渲染线程(UI 线程?)上。

有什么办法可以解决这个问题吗?

谢谢, 马特

编辑:明确地说,是 WB 的创建导致了这一点。如果我删除代码以在 UI 线程上设置图像,并将我的片段渲染为带轮廓的矩形,我仍然可以看到故障。同样,如果我删除 writepixels 调用。简单地创建 WB 会导致问题,我不知道如何阻止它..

最佳答案

尝试使用如下所示的 Dispatcher.CheckAccess() 方法:

        if (_element.Dispatcher.CheckAccess())
        {
            new Action(delegate()
            {
                brush.set_image_brush(wb);

            }));
        }
        else
        {
            _element.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background,
            new Action(delegate()
            {
                brush.set_image_brush(wb);
            }));
        }

关于c# - 在后台线程上创建位图会停止渲染线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22935617/

相关文章:

WPF DataBinding 到代码隐藏中的标准 CLR 属性

C# - 线程的行为是否可以像BackgroundWorkers (winForms) 一样?

C# 使用线程关闭程序/表单

c# - TFS API - 更新工作项字段

c# - 将和弦作为同步声音演奏

c# - 如何安全地迭代 IAsyncEnumerable 以向下游发送集合以批量处理消息

wpf - 指定的 Visual 已经是另一个 Visual 的子级或 CompositionTarget 的根

c# - WPF - 移动 GridSplitter 时列无法正确隐藏

ios - 在当前线程上执行 Parse.com 用户注册 (signUp :) and retrieving the NSError

java - SwingWorker:取消工作线程后调用done()时抛出错误