很多時候寫windows程式都需要結合多執行緒,在.net中用如下得**來建立並啟動乙個新的執行緒。
public
void threadproc();
thread thread = new thread( new threadstart( threadproc ) );
thread.isbackground = true;
thread.start();
「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,當然,這裡展示的是自定義的,.net中還有很多其他型別的委託,可以直接使用,不需要而外宣告。例如: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();
這裡只是我的一些理解,如果有什麼錯誤或者不當的地方,歡迎指出。
C 多執行緒 與 委託
簡單的多執行緒 protected void page load object sender,eventargs e private void mymethod object o 使用委託的多執行緒 public partial class demo form 定義委託 delegate void ...
C Delegate 委託 與多執行緒
很多時候寫windows程式都需要結合多執行緒,在.net中用如下得 來建立並啟動乙個新的執行緒。public void threadproc thread thread new thread new threadstart threadproc thread.isbackground true t...
C Delegate 委託 與多執行緒
很多時候寫windows程式都需要結合多執行緒,在.net中用如下得 來建立並啟動乙個新的執行緒。public void threadproc thread thread new thread new threadstart threadproc thread.isbackground true t...