2009-03-05 75 views
0

好的,請忽略之前的情況。我再也沒有收到錯誤,所以看起來我的問題是,當我更改圖表數據綁定的值時,需要更新圖表。Control.Refresh()跨線程

//以下無視

大家好。我有一個WinForms應用程序,它有一個面板,panel1。後臺線程創建,然後被添加到panel1像這樣

panel1.Controls.AddRange(myArrayOfControls); 

這個偉大的工程,我可以看到我的控制得到補充一些其他控件。但是,當新數據進入另一個線程時,我更新控件父對象中的值,然後需要Refresh()以使顯示更新爲新值。在上下文中調用Refresh(),數據進入的線程或接收更新數據的對象都會導致InvalidOperation異常,因爲需要調用Invoke。我已經嘗試在我的模型對象中使用Invoke,也嘗試在數據傳入並且看起來無法動搖錯誤的線程中使用Invoke。

如果有人有一些指導,我將不勝感激。

更新:這裏有一些更多的信息。我不認爲這需要它,但我錯了。 :)

我有一個對象類MyObject。這個MyObject類是在一個名爲topologyThread的線程中創建的。數據來自dataThread。 MyObject的實例具有一個Panel實例變量,並且Panel有子控件,包括來自System.Windows.Forms.DataVisualization.Charting命名空間的兩個圖表。因此,隨着數據進入dataThread,我更新MyObject對象中的相應數據值,然後需要刷新圖表以顯示更新的數據。

我知道數據處理得很好。在MyObject類中,我將新值記錄到屬性的setter中的Console,並看到新值顯示。

回答

6

您必須從主UI線程執行兩個操作(刷新和更新控件的父對象)。如果你正在從後臺線程修改一個控件而沒有得到一個不幸的異常,因爲這肯定是一個錯誤。

要做到這一點,最好的辦法是使用

theControl.Invoke(new MethodInvoker(MyUpdateMethod)); 

如果你的更新是如何完成的樣本,我們可以就如何正確地從後臺線程調用它一個更好的樣品。

0

JaredPar的回答很好。它在某些情況下可能會導致問題(特別是在表單完成構建之前調用該方法時)。下面是一個較爲穩健的實現(使用擴展方法)

public static class ControlInvokeExtensions 
{ 
    public static void InvokeOnHostThread(Control host, MethodInvoker method) 
    { 
     if (IsHandleCreated) 
      Invoke(new EventHandler(delegate { method(); })); 
     else 
      method(); 
    } 
} 

現在你可以這樣調用它

panel1.InvokeOnHostThread(() => panel1.Controls.AddRange(myArrayOfControls)); 

,或者如果您在表格是:

InvokeOnHostThread(() => panel1.Controls.AddRange(myArrayOfControls)); 
1

JaredPar是一個很好的答案。我想補充一點你的代碼排序的原因。

使用Windows窗體,您可以從其他線程與UI線程交談。在所有情況下這都是非常糟糕的做法。

問題是,當你這樣做的時候,很難抓住,因爲有時UI會像沒有錯誤一樣工作。項目將被添加或更改,UI將反映更改。但其他時間運行相同的確切代碼,它不會工作。

這是從任何其他線程接觸用戶界面的方式。輸出是不一致的,這就是爲什麼非常糟糕的做法。

上帝,我希望我能發表評論。 :)

+1

+1,現在你10代表更接近能夠評論。 :) – 2009-03-05 19:38:35