2012-07-07 54 views
1

我有一個類'userdetails',它有一個名爲'detailschanged'的事件。只要用戶細節發生變化,它就會被提升。
當我在我的新表單中創建'userdetails'(objUserDetails)的新對象時,我將訂閱事件'detailschanged'以向用戶指示datachange。由其他對象引發的工作事件時的跨線程操作

objUserDetails.detailschanged += InformtoUser 

InformtoUser是一種新形式的方法。在InformtoUser方法中,我訪問窗體的控件(比如標籤的文本屬性)。
當控制訪問時,我得到'跨線程操作'錯誤。
如何避免這種交叉線程操作?

回答

1

UI控件只能從UI線程更新。 如果您正在使用的WinForms工作,你應該做的:

mycontrol.Invoke((MethodInvoker)(() => 
{ 
    mycontrol.Text="some text"; 
})); 

如果你是在WPF那麼你應該使用的調度員:

myControl.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => myControl.Text = "")); 
+0

但我只在UI線程中創建該對象。那麼它是如何給十字螺紋? – Olivarsham 2012-07-07 10:42:24

+1

是的,所有對UI組件的訪問都應該在UI線程中完成,而不僅僅是創建:) – GETah 2012-07-07 11:07:03

3

這裏的問題是線程安全:

訪問Windows窗體控件本質上不是線程安全的。如果您有兩個或更多個線程操縱控件的狀態,則可以強制控件進入不一致狀態。其他線程相關的錯誤是可能的,例如競態條件和死鎖。確保以線程安全的方式訪問您的控件非常重要。

從不是使用Invoke方法創建控件的線程調用控件是不安全的。

在對Windows窗體控件進行任何跨線程調用時,您需要使用Control.Invoke

例如:

delegate void SetTextCallback(string text); 

private void SetText(string text) 
{ 
    if (textBox.InvokeRequired) 
    {  
     SetTextCallback d = new SetTextCallback(SetText); 
     this.Invoke(d, new object[] { text }); 
    } 
    else 
    { 
     textBox.Text = text; 
    } 
} 

或:

this.Invoke((MethodInvoker) delegate { 
    this.textBox.Text = "Some text here"; 
}); 

欲瞭解更多信息,您應該參考How to: Make Thread-Safe Calls to Windows Forms Controls

+0

但我創造了只UI線程對象。那麼它是如何給十字螺紋? – Olivarsham 2012-07-07 10:42:57