我使用WPF成像使用DrawingVisual将文本,三维图形和图像合成在一起。然后将结果呈现为RenderTargetBitmap并作为jpeg保存到磁盘。所有这些都发生在没有可视窗口的代码中。
只要我一次只做一件事,它就能很好地运作。但是,我想看看我是否可以通过使用多个线程来进行渲染来加快速度。每个线程都使用一个创建自己的DrawingContext,DrawingVisual等的对象。但是当我尝试并行访问它们时,我发现了一些虚假的错误。有时,调用线程无法访问此对象,因为另一个线程创建了它"。其他时候,当我添加指向3D几何体时,NullReferenceExceptions从WPF的内部冒出来更加邪恶。
有没有办法确保每个线程都与WPF保持隔离?或者是不可避免的共享状态?
答案 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
)。