C#跨執行緒獲取控制元件的引數
線上程ThreadTask1中需要跨執行緒訪問Form上ComboBoxSerialPort控制元件的Text屬性:
1. 傳統方法
定義一個可返回object的委託(系統庫中沒找到這樣的委託,只好自己寫一個):
delegate object obj_delegate();
void ThreadTask1()
{
string serial = (string)comboBoxSerialPort.Invoke(new obj_delegate(() => { return comboBoxSerialPort.Text; }));
...
}
這個方法的好處是:簡單明瞭,obj_delegate只需要定義一次,其他控制元件都可以使用,在主類預先定義一下,以後整個程式都可以用了。
另一個好處是可以省略變數的宣告,直接在語句中呼叫,類似下面的(這樣看起來還是比較簡潔的):
void ThreadTask1()
{
if ((bool)checkbox1.Invoke(new obj_delegate(() => { return checkbox1.Checked; })))
{
...
}
}
壞處是需要在函式外宣告一個委託,強迫症患者表示非常不爽。
2. 通過陣列的引用來設定返回值
此法雞肋,最開始的想法是把ref引數傳到委託裡面,在委託函式裡給ref引數賦值,結果發現可變引數陣列沒法代入ref引數,只好換成普通陣列來完成。
說它是雞肋是因為可以用方法3來完成。
void ThreadTask1()
{
string[] serial = new string[1];
comboBoxSerialPort.Invoke(new ParameterizedThreadStart(o => ((string[])o)[0] = comboBoxSerialPort.Text), (object)serial);
...
}
3.利用Lamda表示式可以直接訪問本地變數來設定返回值
void ThreadTask1()
{
string serial = null;
comboBoxSerialPort.Invoke(new MethodInvoker(() => { serial = comboBoxSerialPort.Text; }));
...
}
好處是直接在函式裡寫兩行就完成了,思路不會被打斷。
壞處是必須先用一行宣告變數。