我正在編寫一個應用程序,通過GPIB命令與多個設備進行通信,並在某些設備上運行測試。我建立了一個類TestProcedure,它將啓動一個新線程並運行測試。在整個測試過程中,我已經設置了幾個自定義事件來將信息發送回GUI。下面是一個簡單事件的例子:C#:事件和線程安全GUI更新
public event InformationEventHandler<string> TestInfoEvent;
/// <summary>
/// Event raised when information should be passed back to the main testing form.
/// </summary>
/// <param name="s">Information to send back to form.</param>
private void OnInfo(string s)
{
if (TestInfoEvent != null)
TestInfoEvent(this, s);
}
這將通過GUI進行處理,更新一個文本框是這樣的:
TheTestProcedure.TestInfoEvent += new TestProcedure.InformationEventHandler<string>
(InfoOccurred);
....
private void InfoOccurred(Object sender, string s)
{
this.textBox1.Text = s + Environment.NewLine + this.textBox1.Text;
if (this.textBox1.Text.Length > 10000)
this.textBox1.Text = this.textBox1.Text.Remove(1000);
}
此事件處理似乎是工作的罰款。我還沒有收到任何跨線程問題,總體而言,它一直在按預期工作。然而,在另一種形式中,我只是添加了一個類似的事件處理程序,它引發了一個跨線程異常。事件觸發,發送一個帶有一些信息的簡單類,這些信息顯示在InputTextBox(一個自定義的ComponentOne控件)中。特定的控件沒有.Invoke方法,所以我正在尋找替代解決方案來異步訪問它。
所以我的問題是,事件處理程序安全地訪問窗體上的控件?如果不是,事件處理程序如何觸發,並且有人可以幫助我教育我,或提供一些鏈接信息,以瞭解事件處理程序如何與窗體控件進行通信?我需要鎖定事件嗎?
我應該添加一個調用到事件本身?這個工作是否與說文字框一樣? 編輯:對不起,剛纔看到你的例子我會看看 – Corey 2012-02-29 18:05:52
你會首先在你的事件處理函數中檢查「InvokeRequired」,如果它返回「true」,你需要使用'的BeginInvoke()'。如果返回值爲'false',那麼您已經在UI線程中,因此您可以直接安全地訪問控件(例如,'txtName.Text = ...;'是有效的,如果您在錯誤的線程中,可能會失敗。) – xxbbcc 2012-02-29 18:07:53
我修正了引用'BeginInvoke()'的答案,因爲你可能需要這個,而不是'Control.Invoke()'。 – xxbbcc 2012-02-29 18:11:38