多线程图像合成

时间:2012-07-27 00:34:55

标签: wpf multithreading rendertargetbitmap drawingcontext drawingvisual

我使用WPF成像使用DrawingVisual将文本,三维图形和图像合成在一起。然后将结果呈现为RenderTargetBitmap并作为jpeg保存到磁盘。所有这些都发生在没有可视窗口的代码中。

只要我一次只做一件事,它就能很好地运作。但是,我想看看我是否可以通过使用多个线程来进行渲染来加快速度。每个线程都使用一个创建自己的DrawingContext,DrawingVisual等的对象。但是当我尝试并行访问它们时,我发现了一些虚假的错误。有时,调用线程无法访问此对象,因为另一个线程创建了它"。其他时候,当我添加指向3D几何体时,NullReferenceExceptions从WPF的内部冒出来更加邪恶。

有没有办法确保每个线程都与WPF保持隔离?或者是不可避免的共享状态?

3 个答案:

答案 0 :(得分:0)

您是否可能意外地在线程中使用相同的资源?您的处理代码中是否包含任何lamda表达式或匿名方法?

答案 1 :(得分:0)

尤里卡。我在线程池线程which is apparently a no-no when working with WPF中创建了我的对象。相反,需要从调度程序线程创建所有对象。顺便说一句,这也清除了我没有发现的可怕的内存泄漏。

我原来的班级定义如下:

public class Compositor
{
    private int _width;
    private int _height;
    private DrawingVisual _drawingVisual;
    private DrawingContext _drawingContext;
    private bool _isReady = false;
    public void Reset(int width, int height)
    {
        _width = width;
        _height = height;
        _drawingVisual = new DrawingVisual();
        _drawingContext = _drawingVisual.RenderOpen();
        _isReady = true;
    }
    // ... compositing methods below
}

为了纠正,我让我的类继承自DispatcherObject,然后使用Dispatcher属性来实例化我的对象。

public class Compositor : DispatcherObject
{
    private int _width;
    private int _height;
    private DrawingVisual _drawingVisual;
    private DrawingContext _drawingContext;
    private bool _isReady = false;
    public void Reset(int width, int height)
    {
        Dispatcher.Invoke(
            new Action(
                () =>
                    {
                        _width = width;
                        _height = height;
                        _drawingVisual = new DrawingVisual();
                        _drawingContext = _drawingVisual.RenderOpen();
                        _isReady = true;
                    }));
    }
    // ... compositing methods below
}

答案 2 :(得分:0)

来自MSDN

  

派生自DispatcherObject的对象具有线程关联性。

     

派生自Freezable的对象在冻结时是自由线程的。有关更多信息,请参阅Freezable对象概述。

使用位图,画笔和其他应该在UI线程上真正使用(不仅仅是创建)的类时遇到了类似的问题。

这很烦人,因为人们希望利用WPF渲染的功能来并行处理领域,但这似乎是不可能的(除了某些情况,比如用指针更新WriteableBitmap)。