C 窗體 UI執行緒委託

2021-09-30 01:10:48 字數 2510 閱讀 5753

很多時候寫windows程式都需要結合多執行緒,在c#中用如下得**來建立並啟動乙個新的執行緒。

thread thread = new thread(new threadstart(threadproc));//例項化乙個執行緒

thread.isbackground = true;//將執行緒改為後台執行緒

thread.start();//開啟執行緒

但是很多時候,在新的執行緒中,我們需要與ui(windows窗體設計器使用者介面)進行互動,在c#中不允許直接這樣做。可以參考msdn中的描述。

「windows 窗體」使用單執行緒單元 (sta) 模型,因為「windows 窗體」基於本機win32視窗,而win32視窗從本質上而言是單元執行緒。sta模型意味著可以在任何執行緒上建立視窗,但視窗一旦建立後就不能切換執行緒,並且對它的所有函式呼叫都必須在其建立執行緒上發生。除了windows窗體之外,.net framework 中的類使用自由執行緒模型。

sta模型要求需從控制項的非建立執行緒呼叫的控制項上的任何方法必須被封送到(在其上執行)該控制項的建立執行緒。基類control為此目的提供了若干方法(invoke、begininvoke 和 endinvoke)。invoke生成同步方法呼叫;begininvoke生成非同步方法呼叫。

windows窗體中的控制項被繫結到特定的執行緒,不具備執行緒安全性。因此,如果從另乙個執行緒呼叫控制項的方法,那麼必須使用控制項的乙個invoke方法來將呼叫封送到適當的執行緒。

正如所看到的,必須呼叫invoke方法,而begininvoke可以認為是invoke的非同步版本。呼叫方法如下:

public delegate void outdelegate(string text);

public void outtext(string text)

outdelegate outdelegate = new outdelegate( outtext );

this.begininvoke(outdelegate, new object);

如果需要在另外乙個執行緒裡面對ui進行操作,需要乙個類似outtext的函式,還需要乙個該函式的委託delegate,當然,這裡展示的是自定義的。

該屬性可用於確定是否必須呼叫 invoke 方法,當不知道什麼執行緒擁有控制項時這很有用。

也就是說通過判斷invokerequired可以知道是否需要用委託來呼叫當前控制項的一些方法,如此可以把outtext函式修改一下:

public delegate void outdelegate(string text);

public void outtext(string text)

); return;

}}

注意,這裡的函式沒有返回,如果有返回,需要呼叫invoke或者endinvoke來獲得返回的結果,不要因為包裝而丟失了返回值。如果呼叫沒有完成,invoke和endinvoke都將會引起阻塞。

現在如果我有乙個執行緒函式如下:

public void threadproc()

}

如果迴圈的次數很大,或者漏了thread.sleep(1000);,那麼你的ui肯定會停止響應,想知道原因嗎?看看begininvoke前面的物件,沒錯,就是this,也就是主線程,當你的主線程不停的呼叫outtext的時候,ui當然會停止響應。

與以前vc中建立乙個新的執行緒需要呼叫afxbeginthread函式,該函式中第乙個引數就是執行緒函式的位址,而第二個引數是乙個型別為lpvoid的指標型別,這個引數將傳遞給執行緒函式。現在我們沒有辦法再使用這種方法來傳遞引數了。我們需要將傳遞給執行緒的引數和執行緒函式包裝成乙個單獨的類,然後在這個類的建構函式中初始化該執行緒所需的引數,然後再將該例項的執行緒函式傳遞給thread類的建構函式。**大致如下:

public class procclass

public void threadproc()

}procclass threadproc = new procclass("use thread class");

thread thread = new thread( new threadstart( threadproc.threadproc ) );

thread.isbackground = true;

thread.start();

就是這樣,需要建立乙個中間類來傳遞執行緒所需的引數。

那麼如果我的執行緒又需要引數,又需要和ui進行互動的時候該怎麼辦呢?可以修改一下**:

public class procclass

public void threadproc()

}procclass threadproc = new procclass("use thread class", new outdelegate(outtext));

thread thread = new thread( new threadstart( threadproc.threadproc ) );

thread.isbackground = true;

thread.start();

C 利用委託跨執行緒更新UI資料

在使用c 的過程中,難免會用到多執行緒,而用多執行緒之後,執行緒如何與介面互動則是乙個非常頭疼的問題。其實不僅僅是介面,一般情況下,我們往往需要獲得執行緒的一些資訊來確定執行緒的狀態。比較好的方式是用委託實現,看例子 注 本例利用委託和跨執行緒訪問技術,用介面上的兩個label控制項實時顯示執行緒的...

C 多執行緒使用委託修改介面UI

多執行緒修改介面時,需要考慮到一般多執行緒讀髒資料,資料重寫等問題,所以一般把多線成修改介面的方法交由ui執行緒本身執行,這樣就使多執行緒修改ui變成單執行緒修改了,問題得到簡化 多執行緒如何將修改介面的方法交給ui執行緒呢,就是用c 的委託了 我一般的做法如下 delegate void upda...

C 利用委託跨執行緒更新UI資料

在使用c 的過程中,難免會用到多執行緒,而用多執行緒之後,執行緒如何與介面互動則是乙個非常頭疼的問題。其實不僅僅是介面,一般情況下,我們往往需要獲得執行緒的一些資訊來確定執行緒的狀態。比較好的方式是用委託實現,看例子 注 本例利用委託和跨執行緒訪問技術,用介面上的兩個label控制項實時顯示執行緒的...