2009-04-29 38 views
3

...或...WPF Canvas:Children.Add()挂在后台线程上?

“我觉得WPF深处有什么邪恶?

我在后台线程上创建一个Canvas并将其渲染为位图。我已经在生产代码中工作了一年多,现在没有问题。我做到以下几点:

  • 创建一个Canvas对象
  • 创建一个新的名称范围对象
  • 分配一个名称范围画布
  • 平局任何我想要的画布上
  • 呼叫canvas.Measure( )与画布的大小
  • 调用canvas.Arrage()与画布的可用矩形
  • 调用canvas.UpdateLayout()
  • 渲染画布

拉伸步骤中,我一直就叫canvas.Children.Add()把UI元素到画布上。这一直工作。

现在,出于一些不可理解的原因,在我正在处理的应用程序中的一个特定情况下,调用canvas.Children.Add()会不确定地挂起,阻塞我的后台线程。我想不出我在一年多的代码和这个特定的案例之间做了什么不同的事情。

任何人都可以提出可能的原因,为什么一个调用canvas.Children.Add()会像这样挂?

编辑:后台线程是STA线程(后台线程处理模型放在适当的位置,因为我无法处理在MTA线程使用WPF图像),因此线程单元模型不应该是罪魁祸首。

编辑#2:虽然我理解人们为什么建议我尝试Dispatcher.BeginInvoke()从我的后台线程,我不喜欢这样的选择,原因有两个:

  1. 我想我的背景线程处理在该线程上是同步的。我的后台线程有一个其他线程提交图像作业的队列,而我的后台线程处理每个作业的处理过程。使用Dispatcher.BeginInvoke()添加了我宁愿避免的另一复杂层。
  2. 我从来没有需要直到现在。在我的后台线程上同步处理这个后台处理只是简单的工作。我试图确定可能会导致此代码无法工作的奇怪边缘案例可能会有所不同。如果我无法实现它,我将最终重写这个没有WPF的处理代码,我也宁愿避免。

回答

2

你使用哪种公寓模式作为后台线程?

我相信WPF需要在STA线程上运行。当你产生后台线程时,尝试将它的公寓设置为STA。

更新:

如果STA线程是没有问题的,那么我会尝试打破你的画布绘制成块。基本上,如果你做一个:从你的线程

Dispatcher.BeginInvoke(...)

,所提供的委托被压到调度队列的后面,允许其他排队的任务来执行。

更新2:

您也可以尝试调试成画布源代码对象使用.NET Framework参考来源。您可以通过打开“工具” - >“选项”下的调试选项中的“启用.net框架源代码步进”来启用该功能。

+0

这是一个STA线程。这是我不得不将处理任务卸载到后台线程的原因 - 调用线程是我们的情况始终是MTA。 – 2009-04-29 17:17:19

+0

不会Dispatcher.BeginInvoke()击败WPF处理后台线程的目的?我不想将任务分流回UI线程.. – 2009-04-29 17:58:11

-1

尝试在后台线程中调用Dispatcher.Run()。