2009-04-29 133 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()。