delegate 與 多執行緒

2021-03-31 08:56:58 字數 3686 閱讀 6833

很多時候寫

windows

程式都需要結合多執行緒,在

.***

中用如下得**來建立並啟動乙個新的執行緒。

public

void threadproc();

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

thread.isbackground = true;

thread.start();

但是很多時候,在新的執行緒中,我們需要與

ui進行互動,在

.***

中不允許我們直接這樣做。可以參考

msdn

中的描述:

「windows

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

,當然,這裡展示的是自定義的,

.***

中還有很多其他型別的委託,可以直接使用,不需要而外宣告。例如:

methodinvoker

和eventhandler

,這兩種型別委託的函式外觀是固定的,

methodinvoker

是void function()

型別的委託,而

eventhandler

是void function(object, eventargs)

型別的委託,第乙個不支援引數,第二中的引數型別和數量都是固定的,這兩種委託可以很方便的呼叫,但是缺乏靈活性。請注意

begininvoke

前面的物件是

this

,也就是主線程。現在再介紹

control.invokerequired

,control

是所有控制項的基類,對於這個屬性

msdn

的描述是:

獲取乙個值,該值指示呼叫方在對控制項進行方法呼叫時是否必須呼叫

invoke

方法,因為呼叫方位於建立控制項所在的執行緒以外的執行緒中。

該屬性可用於確定是否必須呼叫

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();

這裡只是我的一些理解,如果有什麼錯誤或者不當的地方,歡迎指出。

多執行緒 Java多執行緒與併發

實現的方式主要有三種 執行緒的狀態 基本差別 最主要的本質區別 兩個概念 鎖池 假設執行緒a已經擁有了某個物件 不是類 的鎖,而其他執行緒b c想要呼叫這個物件的某個synchronized方法 或者塊 由於b c執行緒在進入物件的synchronized方法 或者塊 之前必須先獲得該物件鎖的擁有權...

MFC多執行緒與多執行緒的同步

dword winapi threadproc lpvoid lpparameter 注意這裡threadproc這個名字是可以按自己的要求修改的 handle winapi createthread lpsecurity attributes lpthreadattributes,安全性 size...

多執行緒 單例模式與多執行緒

一 前言 如何使單例模式遇到多執行緒是安全的 正確的?我們在學習設計模式的時候知道單例模式有懶漢式和餓漢式之分。簡單來說,餓漢式就是在使用類的時候已經將物件建立完畢,懶漢式就是在真正呼叫的時候進行例項化操作。二 餓漢式 多執行緒 public class myobject public static...