1. 程式人生 > >C#跨執行緒獲取控制元件的引數

C#跨執行緒獲取控制元件的引數

線上程ThreadTask1中需要跨執行緒訪問Form上ComboBoxSerialPort控制元件的Text屬性:

1. 傳統方法

定義一個可返回object的委託(系統庫中沒找到這樣的委託,只好自己寫一個):

delegate object obj_delegate();

然後執行緒中Invoke來獲取:

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; }));
    ...
}

這個方法比方法2簡潔很多。

好處是直接在函式裡寫兩行就完成了,思路不會被打斷。

壞處是必須先用一行宣告變數。