2012-05-25 140 views
2

WPF控件我有一個異步運行Task,當它完成這樣的觸發事件。但是當我嘗試這樣做時,會導致一個異常:The calling thread must be STA, because many UI components require this。調用方法InitializeComponent()時,類構造函數中發生異常。創建從一個單獨的線程

據我所知,通常acessing WPF從單獨threades控制使用Dispatcher.Invoke處理,它總是爲我工作,所以我試了一下:

Dispatcher.Invoke(new Action(() => 
{ 
    InitializeComponent(); 
})); 

但在這種情況下異常不斷髮生的歷史。 那麼任何人都可以告訴如何從一個單獨的線程創建一個WPF控件的實例嗎? 或者,也許這將是一個更好的方法來將主題UI線程完成事件,如果是的話,我該怎麼做?

任何幫助表示讚賞。謝謝。

回答

3

您必須使用與UI線程關聯的Dispatcher實例。如果你寫的東西是這樣的:在任務體

Dispatcher.Invoke(new Action(() => 
{ 
    InitializeComponent(); 
})); 

,您使用的是調用線程,這可以從池中後臺線程的調度。

無論如何,有了任務,你不應該直接使用Dispatcher。使用適當的任務調度程序:

var ui = TaskScheduler.FromCurrentSynchronizationContext(); 
Task.Factory.ContinueWhenAll(tasks.ToArray(), 
    result => 
    { 
     // put you UI calls here 

    }, CancellationToken.None, TaskContinuationOptions.None, ui); 

其中tasks是任務的順序來使用默認調度執行。

+0

這似乎上班,謝謝! – Slippy

1

我已經在過去

Dispatcher.Invoke(DispatcherPriority.Normal, 
        new Action(
         delegate() 
         { 
          //access control created by main thread 
          textBlock.Text = msg; 
         } 
         )); 
+0

因爲我們正在創建一個'Control',所以我會使用DispatcherPriority.Render。 – Guillaume

+0

我已經能夠添加控制到父母這種方式至少... EX:panel.Children.Add(新的MyControl())等 – TGH

+0

謝謝,但'Dispatcher.Priority'在我的情況下沒有改變( – Slippy

1

從另一個線程調用構造函數在InitializeComponent這樣做似乎是自找麻煩。該對象還沒有(我們在構造函數中)

將其回收到UI線程通常會做到這一點,但在構造函數期間對我來說看起來像個壞主意。

如果要異步初始化控件,只需訂閱加載的事件,以便知道該對象在那裏,生成一個執行一些計算/數據檢索的線程並將數據編組回到UI線程以顯示它。