在创建昂贵的WPF对象和多线程

时间:2010-09-29 21:30:44

标签: wpf multithreading dispatcher

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

我正在使用第三方库生成一些强烈的元素,这可能需要大约0.75秒 - 1.5秒来渲染。生成一个并不是太糟糕,但是当我需要创建其中的5个以便立即显示时,它会明显锁定UI(包括进度微调器)。不幸的是,没有任何其他地方可以创建它们,因为WPF是线程仿射。

我已经尝试DispatcherPriority.Background,但这还不够。处理这个问题的推荐方法是什么?

1 个答案:

答案 0 :(得分: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次而不是一次。这使UI有机会定期响应输入。