2010-09-29 36 views
1

多线程编程中的经典建议是在后台线程上执行繁重的处理器工作,并将结果返回到UI线程以进行小处理(更新标签等)。如果生成WPF元素本身就是昂贵的操作呢?关于创建昂贵的WPF对象和多线程

我正在与第三方库合作生成一些激烈的元素,这些元素可能需要0.75s-1.5s来渲染。生成一个并不算太糟糕,但是当我需要创建其中的5个来立即显示时,它明显地锁定了UI(包括进度微调)。不幸的是,没有其他地方可以创建它们,因为WPF是线程仿射。我已经试过DispatcherPriority.Background但它不够。处理这个问题的建议方法是什么?

+2

使用另一个库...如果创建一个UIElement的实例需要这么长时间,它可能相当不好实现 – 2010-09-29 21:49:33

+0

是否这些元素的创建或渲染很昂贵? – Oskar 2010-09-30 13:21:27

回答

1

如果创建的对象派生自Freezable,那么实际上可以在与UI线程不同的线程上创建它们 - 您只需在工作线程上调用Freeze,然后就可以传输他们结束了。但是,对于不能从Freezable派生的项目,这无济于事。

您是否尝试过每次创建一个?下面的例子没有做任何有用的工作,但它确实表明了在小位做了很多工作的基本结构是如何:

int count = 100; 
Action slow = null; 
slow = delegate 
{ 
    Thread.Sleep(100); 
    count -= 1; 
    if (count > 0) 
    { 
     Dispatcher.BeginInvoke(slow, DispatcherPriority.Background); 
    } 
}; 
Dispatcher.BeginInvoke(slow, DispatcherPriority.Background); 

的“工作”这里是睡了十分之一秒。 (所以如果你用真正的工作来替代它,你会得到相同的行为。)这样做的次数是100次,所以这是总共10秒的“工作”。用户界面在整个过程中保持合理的响应 - 例如拖动窗口变得不那么流畅,但它非常实用。将这两个背景优先级更改为正常,并锁定应用程序。

这里的关键是我们在完成排队的每一小部分工作后最终返回 - 我们最终调用Dispatcher.BeginInvoke 100次而不是一次。这使得用户界面有机会定期回应投入。