2012-03-12 144 views
1

我有一個線程在wpf中生成GUI元素。畫布是有繪製對象(矩形等...)Task.Factory和線程之間的通信

WPF線程調用另一個線程讓我們命名它的計算線程。該線程計算要在畫布中顯示的元素的大小和位置等。

我想讓這兩部分(GUI和計算)在不同的線程中運行。 「計算線程」基於一個沒有引用wpf功能的庫。

現在我想顯示由wpf線程顯示的計算線程的中間數據。 我做這樣的說法:

的計算線程觸發一個事件(DataReady)由WPF的線程來實現:

void MyRegStringObject_DataReady() 
{ 
    if (DebugMode) 
    MyDrawingBoard.DrawRegElements(); 
} 

現在的問題是,這將引發錯誤: 「調用線程不能訪問這個對象,因爲不同的線程擁有它」

這裏有一些在stackoverflow引用這個錯誤的回答問題,但沒有一個可以幫助我的情況。

功能DrawRegElements()要清除畫布對象(除其他事項外):

curCanvas.Children.Clear(); 

在在引發錯誤的代碼這個位置。 似乎由calc-thread觸發的函數MyRegStringObject_DataReady也被calc-thread所支付。但是在類中定義了wpf-thread基於。

我該如何解決這個問題?有人有什麼主意嗎? 順便說一句: 的鈣線程稱爲是這樣的:

CalcElements = Task.Factory.StartNew<bool>(MyRegStringObject.CalcRegElements); 

當線程完成我定義:

CalcElements.ContinueWith((FinishCalcRegElements) => 
{ 
    MyDrawingBoard.DrawRegElements(); 
}, CancellationToken.None, TaskContinuationOptions.None, 
TaskScheduler.FromCurrentSynchronizationContext()); 

沒有異議。 Everythins運行完美。 ContinueWith中定義的函數似乎由wpf-thread所支持。

回答

2

錯誤消息很簡單,您正試圖從現在擁有的線程訪問UI元素。委派這項工作,WPF調度員,其與主UI線程相關聯,這將發佈從輔助線程的所有消息UI線程:

Application.Current.Dispatcher.BeginInvoke((ThreadStart)delegate 
    {    
     MyDrawingBoard.DrawRegElements(); 
    }); 

爲確保您使用的是正確的調度,與主UI線程相關聯,您可以將它作爲參數傳遞給工作線程代碼,因此只需從主UI線程傳遞Dispatcher.Current,否則在輔助線程中調用Dispatcher.CurrentDispatcher將初始化與調用工作線程關聯的新實例。或者只是使用Application.Current.Dispatcher,它會引用主UI線程的分派器。

PS:

但它是在類中定義的WPF線程是基於

這是錯誤的假設,類本身不相關的任何線索。 Concrtete類實例是。因此,您可以在UI或工作線程中創建UI /非UI相關的類。

同樣重要的點在哪個線程DataReady事件已經被解僱?

+0

當你說'Dispatcher.Current'你的意思是[Dispatcher.CurrentDispatcher](http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.currentdispatcher.aspx),對不對?我猜想MyDrawingBoard是某種WPF控件,所以'MyDrawingBoard.Dispatcher.BeginInvoke'就可以。 – Clemens 2012-03-12 10:52:19

+0

右'CurrentDispatcher',已修復。你試過這個嗎? – sll 2012-03-12 10:58:24

+0

@ sll Dispatcher.CurrentDispatcher.BeginInvoke並沒有真正的工作我不知道爲什麼,但UI線程接收到工作線程觸發的事件,但DrawRegElements沒有被調用。它只在最後被調用(當工作線程完成時)。 – manton 2012-03-12 11:05:41