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

时间:2014-04-08 11:28:25

标签: c# wpf multithreading graphics

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

出于性能原因,我们在后台进行所有加载,并在其自己的图形中呈现每个线段。这很好用,手动滚动视图(或跳转到特定位置)可以提供非常好的性能。

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

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导致了问题,我不知道如何阻止它..

1 个答案:

答案 0 :(得分:0)

尝试使用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);
            }));
        }