在system.threading 命名空間下,包含了用於建立和控制線程的thread 類。對執行緒的常用操作有:啟動執行緒、終止執行緒、合併執行緒和讓執行緒休眠等。
在使用執行緒前,首先要建立乙個執行緒。其一般形式為:
thread t=new thread(enterpoint);其中enterpoint 為執行緒的入口,即執行緒開始執行的方法。在託管**中,通過委託處理執行緒執行的**。例如:
thread t=new thread(new threadstart(methodname));建立執行緒例項後,就可以呼叫start 方法啟動執行緒了。
執行緒啟動後,當不需要某個執行緒繼續執行的時候,有兩種終止執行緒的方法。
一種是事先設定乙個布林變數,在其他執行緒中通過修改該變數的值作為傳遞給該執行緒是否需要終止的判斷條件,而在該執行緒中迴圈判斷該條件,以確定是否退出執行緒,這是結束執行緒的比較好的方法,實際程式設計中一般使用這種方法。
第二種方法是通過呼叫thread 類的abort 方法強行終止執行緒。例如:
t.abort();abort 方法沒有任何引數,執行緒一旦被終止,就無法再重新啟動。由於abort 通過丟擲異常強行終止結束執行緒,因此在實際程式設計中,應該盡量避免採用這種方法。
join 方法用於把兩個並行執行的執行緒合併為乙個單個的執行緒。如果乙個執行緒t1 在執行的過程中需要等待另乙個執行緒t2 結束後才能繼續執行,可以在t1 的程式模組中呼叫t2 的join()方法。例如:
t2.join();這樣t1 在執行到t2.join()語句後就會處於阻塞狀態,直到t2 結束後才會繼續執行。
但是假如t2 一直不結束,那麼等待就沒有意義了。為了解決這個問題,可以在呼叫t2 的join 方法的時候指定乙個等待時間,這樣t1 這個執行緒就不會一直等待下去了。例如,如果希望將t2 合併到t1 後,t1 只等待100 毫秒,然後不論t2 是否結束,t1 都繼續執行,就可以在t1中加上語句:
t2.join(100);join 方法通常和abort 一起使用。
由於呼叫某個執行緒的abort 方法後,我們無法確定系統清理**的工作什麼時候才能結束,因此如果希望主線程呼叫了子執行緒的abort 方法後,主線程不必一直等待,可以呼叫子執行緒的join 方法將子執行緒連線到主線程中,並在連線方法中指定乙個最大等待時間,這樣就能使主線程繼續執行了。
在多執行緒應用程式中,有時候並不希望某乙個執行緒繼續執行,而是希望該執行緒暫停一段時間,等待其他執行緒執行之後再繼續執行。這時可以呼叫thread 類的sleep 方法,即讓執行緒休眠。例如:
thread.sleep(1000);這條語句的功能是讓當前執行緒休眠1000 毫秒。
注意,呼叫sleep 方法的是類本身,而不是類的例項。休眠的是該語句所在的執行緒,而不是其他執行緒。
當執行緒之間爭奪cpu 時間片時,cpu 是按照執行緒的優先順序進行服務的。在c#應用程式中,可以對執行緒設定五個不同的優先順序,由高到低分別是highest、abovenormal、normal、belownormal 和lowest。在建立執行緒時如果不指定其優先順序,則系統預設為normal。假如想讓一些重要的執行緒優先執行,可以使用下面的方法為其賦予較高的優先順序:
thread t=new thread(new通過設定執行緒的優先順序可以改變執行緒的執行順序,所設定的優先順序僅僅適用於這些執行緒所屬的程序。threadstart(enterpoint));
t.priority=threadpriority.abovenormal;
注意,當把某執行緒的優先順序設定為highest 時,系統上正在執行的其他執行緒都會終止,所以使用這個優先級別時要特別小心。
執行緒池是一種多執行緒處理形式,為了提高系統效能,在許多地方都要用到執行緒池技術。例如,在乙個c/s 模式的應用程式中的伺服器端,如果每到乙個請求就建立乙個新執行緒,然後在新執行緒中為其請求服務的話,將不可避免的造成系統開銷的增大。實際上,建立太多的執行緒可能會導致由於過度使用系統資源而耗盡記憶體。為了防止資源不足,伺服器端應用程式應採取一定的辦法來限制同一時刻處理的執行緒數目。
執行緒池為執行緒生命週期的開銷問題和資源不足問題提供了很好的解決方案。通過對多個任務重用執行緒,執行緒建立的開銷被分攤到了多個任務上。其好處是,由於請求到達時執行緒已經存在,所以無意中也就消除了執行緒建立所帶來的延遲。這樣,就可以立即為新執行緒請求服務,使其應用程式響應更快。而且,通過適當地調整執行緒池中的執行緒數目,也就是當請求的數目超過了規定的最大數目時,就強制其他任何新到的請求一直等待,直到獲得乙個執行緒來處理為止,從而可以防止資源不足。
執行緒池適用於需要多個執行緒而實際執行時間又不多的場合,比如有些常處於阻塞狀態的執行緒。當乙個應用程式伺服器接受大量短小執行緒的請求時,使用執行緒池技術是非常合適的,它可以大大減少執行緒建立和銷毀的次數,從而提高伺服器的工作效率。但是如果執行緒要求執行的時間比較長的話,那麼此時執行緒的執行時間比執行緒的建立時間要長得多,僅靠減少執行緒的建立時間對系統效率的提高就不是那麼明顯了,此時就不適合使用執行緒池技術,而需要借助其他的技術來提高伺服器的服務效率。
同步是多執行緒中乙個非常重要的概念。所謂同步,是指多個執行緒之間存在先後執行順序的關聯關係。如果乙個執行緒必須在另乙個執行緒完成某個工作後才能繼續執行,則必須考慮如何讓
其保持同步,以確保在系統上同時執行多個執行緒而不會出現邏輯錯誤。
當兩個執行緒t1 和t2 有相同的優先順序,並且同時在系統上執行時,如果先把時間片分給t1使用,它在變數variable1 中寫入某個值,但如果在時間片用完時它仍沒有完成寫入,這時由於時間片已經分給t2 使用,而t2 又恰好要嘗試讀取該變數,它可能就會讀出錯誤的值。這時,如果使用同步僅允許乙個執行緒使用variable1,在該執行緒完成對variable1 的寫入工作後再讓t2讀取這個值,就可以避免出現此類錯誤。
為了對執行緒中的同步物件進行操作,c#提供了lock 語句鎖定需要同步的物件。lock 關鍵字確保當乙個執行緒位於**的臨界區時,另乙個執行緒不進入臨界區。如果其他執行緒試圖進入鎖定的**,則它將一直等待(即被阻塞),直到該物件被釋放。比如執行緒t1 對variable1 操作時,為了避免其他執行緒也對其進行操作,可以使用lock 語句鎖定variable1,實現**為:
lock注意,鎖定的物件一定要宣告為private,不要鎖定public 型別的物件,否則將會使lock語句無法控制,從而引發一系列問題。(variable1)
另外還要注意,由於鎖定乙個物件之後,其他任何執行緒都不能訪問這個物件,需要使用該物件的執行緒就只能等待該物件被解除鎖定後才能使用。因此如果在鎖定和解鎖期間處理的物件過多,就會降低應用程式的效能。
還有,如果兩個不同的執行緒同時鎖定兩個不同的變數,而每個執行緒又都希望在鎖定期間訪問對方鎖定的變數,那麼兩個執行緒在得到對方變數的訪問權之前都不會釋放自己鎖定的物件,從而產生死鎖。在編寫程式時,要注意避免這類操作引起的問題。
【例】執行緒的基本用法
(1) 新建乙個名為threadexample 的windows 應用程式,介面設計如圖所示。
(2) 向設計窗體拖放乙個timer 元件,不改變自動生成的物件名。
(3) 新增命名空間引用:
using system.threading;(4) 在建構函式上方新增字段宣告:
stringbuilder sb = new(5) 直接新增**:stringbuilder();
thread thread1;
thread thread2;
privates)}(6) 分別在【啟動執行緒】和【終止執行緒】按鈕的click 事件中新增**:public
void
method1()
}public
void
method2()
}
private(7) 在timer1 的tick 事件中新增**:void buttonstart_click(object
sender, eventargs e)
private
void buttonabort_click(object
sender, eventargs e)
private(8) 按鍵編譯並執行,單擊【啟動執行緒】後,再單擊【終止執行緒】,從執行結果中可以看到,兩個具有相同優先順序的執行緒同時執行時,在richtextbox1 中新增的字元個數基本上相同。void timer1_tick(object
sender, eventargs e)
else
}
C 執行緒類Thread初步
net 基礎類庫的 system.threading 命名空間提供了大量的類和介面支援多執行緒。這個命名空間有很多的類。system.threading.thread 類是建立並控制線程,設定其優先順序並獲取其狀態最為常用的類。他有很多的方法,在這裡我們將就比較常用和重要的方法做一下介紹 threa...
C 執行緒類Thread初步
net 基礎類庫的 system.threading 命名空間提供了大量的類和介面支援多執行緒。這個命名空間有很多的類。system.threading.thread 類是建立並控制線程,設定其優先順序並獲取其狀態最為常用的類。他有很多的方法,在這裡我們將就比較常用和重要的方法做一下介紹 threa...
C 執行緒類Thread初步
net 基礎類庫的system.threading命名空間提供了大量的類和介面支援多執行緒。這個命名空間有很多的類。system.threading.thread類是建立並控制線程,設定其優先順序並獲取其狀態最為常用的類。他有很多的方法,在這裡我們將就比較常用和重要的方法做一下介紹 thread.s...