一個執行緒被定義為一個程式的執行路徑。每個線程都定義了一個獨特的流量控制。如果你的應用程式涉及複雜的和耗時的操作,例如資料庫存取或一些激烈的I/O 操作,那麼往往會設定不同的執行路徑或線程,每個線程執行一個特定的工作是非常有益的。
執行緒是輕量級的行程。使用線程的一個常見的例子是現代作業系統並行程式設計的實作。使用線程節省了CPU 週期的損失,並提高了應用效率。
到目前為止我們編譯好的程式在一個執行緒作為一個單一的過程運行,也就是應用程式的運行實例。然而,這樣的應用程式只可以在某一時刻執行一個工作。讓它在同一時間執行多個任務,可以把它分成更小的執行緒。
在.Net ,線程是透過'System.Threading' 的命名空間處理的。創造的system.threading.thread 類型的變數可讓你建立一個新執行緒開始工作。它允許你在一個單獨的線程中創建和訪問獨立的線程。
一個線程是由一個線程物件創建的,並給出了它的建構函數的開啟線程的參考。
ThreadStart childthreat = new ThreadStart(childthreadcall);
一個執行緒的生命週期開始於system.threading.thread 類別的一個物件被創建,結束於執行緒被終止或執行完成。
以下是在一個執行緒的生命週期的各種狀態:
待開啟狀態:該執行緒的實例被建立但啟動方法尚未被呼叫的情況。
就緒狀態:當執行緒準備好執行並且在等待CPU 週期的情況。
不可運行狀態:執行緒不能被運行的情況,有以下幾種可能:
當前睡眠的方法被調用
等待的方法被調用
被I/O 操作阻塞
死亡狀態:執行緒執行完畢或已中止的情況。
Thread 類別中的優先權屬性主要是相對於其他執行緒指定一個執行緒的優先權。 .NET 執行階段選擇具有最高優先權的就緒執行緒。優先權可分為:
高於正常
低於正常
最高
最低
正常
一旦一個執行緒被創建,系統就會使用Thread 類別的優先權設定係統設定好它的優先權。
NewThread.Priority = ThreadPriority.Highest;
線程類別具有以下重要特性:
屬性 | 描述 |
---|---|
CurrentContext | 取得目前正在執行的線程的內容。 |
CurrentCulture | 取得或設定目前執行緒的環境。 |
CurrentPrinciple | 取得或設定目前進程關於基於角色的安全機制的原則。 |
CurrentThread | 獲取當前正在運行的線程。 |
CurrentUICulture | 取得或設定目前執行的程序的資源管理器用於尋找特定資源的目前環境。 |
ExecutionContext | 取得包含有關目前執行緒的上下文資訊的ExecutionContext 物件。 |
IsAlive | 取得一個值,指示目前執行緒的執行狀態。 |
IsBackground | 後台取得或設定一個值指示執行緒是否為後台執行緒。 |
IsThreadPoolThread | 取得一個值,指示執行緒是否屬於託管執行緒池。 |
ManagedThreadId | 取得託管執行緒的目前唯一識別碼。 |
Name | 取得或設定線程的名稱。 |
Priority | 取得或設定一個值,表示一個執行緒的調度優先權。 |
ThreadState | 取得一個值,包含目前執行緒的狀態。 |
線程類別具有以下重要方法:
方法 | 描述 |
---|---|
Abort | 呼叫一個ThreadAbortException 開始終止執行緒的過程,呼叫此方法通常會終止執行緒。 |
AllocateDataSlot | 向所有執行緒分配一個未命名的資料槽。為了獲得更好的效能,使用標有ThreadStaticAttribute 屬性的域。 |
AllocateNamedDataSlot | 向所有執行緒上分配已命名的資料槽。為了獲得更好的效能,使用的是標示ThreadStaticAttribute 屬性的域。 |
BeginCriticalRegion | 通知宿主執行即將進入程式碼區域,那裡執行緒中止或未處理的異常的影響可能危及其他任務的應用領域。 |
BeginThreadAffinity | 通知主機代管程式碼將要執行,取決於目前的實體作業系統執行緒的識別說明。 |
EndCriticalRegion | 通知宿主執行即將進入程式碼區域,那裡執行緒中止或未處理的異常僅影響目前任務。 |
EndThreadAffinity | 通知宿主託管程式碼執行完成,取決於目前的實體作業系統執行緒的識別說明。 |
FreeNamedDataSlot | 為進程中的所有執行緒消除名稱與槽之間的關聯,為了獲得更好的效能,使用的是標有ThreadStaticAttribute 屬性的域。 |
GetData | 在目前執行緒的目前域從目前執行緒指定的插槽檢索值。為了獲得更好的效能,使用的是標示ThreadStaticAttribute 屬性的域。 |
GetDomain | 傳回目前域中目前正在執行的執行緒。 |
GetDomainID | 傳回唯一的應用程式域識別碼。 |
GetNamedDataSlot | 尋找已命名的資料槽。為了獲得更好的效能,使用的是標示ThreadStaticAttribute 屬性的域。 |
Interrupt | 中斷一個在WaitSleepJoin 執行緒狀態的執行緒。 |
Join | 阻塞呼叫線程,直到某個線程終止,同時繼續執行標準的COM 和SendMessage 。此方法具有不同的重載形式。 |
MemoryBarrier | 同步記憶體存取如下:處理目前執行緒的加速器不能以記憶體存取呼叫MemoryBarrier 後先呼叫記憶體存取執行這種方式對指令重新排序。 |
ResetAbort | 取消目前執行緒的中止請求。 |
SetData | 設定資料在指定的時隙上目前運行的線程,該線程的當前域。為了獲得更好的效能,應用領域有ThreadStaticAttribute 屬性的域。 |
Start | 啟動一個線程。 |
Sleep | 使線程暫停一個時間段。 |
SpinWait | 使線程等待的參數定義的迭代次數。 |
VolatileRead() | 讀取字段的值。最新的值是由電腦的任何處理器寫入,不論處理器或處理器快取的狀態數。此方法具有不同的重載形式。 |
VolatileWrite() | 立即向欄位寫入一個值,這樣的值是對電腦中的所有處理器可見。此方法具有不同的重載形式。 |
Yield | 使呼叫線程執行可以在目前的處理器運行的另一個線程,作業系統選用轉向的縣城 |
下面的例子闡明了對線程類別的使用。該頁面有一個控制標籤顯示子線程傳來的消息。從主程式傳來的訊息直接使用response.write(50) 的方法顯示出來,因此它們出現在頁面的頂部。
原始檔如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="threaddemo._Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional// EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title> Untitled Page </title> </head> <body> <form id="form1 " runat="server"> <div> <h3>Thread Example</h3> </div> <asp:Label ID="lblmessage" runat="server" Text="Label"> </asp:Label> </form> </body> </html>
後台程式碼如下:
using System; using System.Collections; using System.Configuration; using System.Data; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls ; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; using System.Threading; namespace threaddemo { public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { ThreadStart childthreat = new Thcall; ("Child Thread Started <br/>"); Thread child = new Thread(childthreat); child.Start(); Response.Write("Main sleeping for 2 seconds.......<br/>"); Thread.Sleep(2000); Response.Write( "<br/>Main aborting child thread<br/>"); child.Abort(); } public void childthreadcall() { try{ lblmessage.Text = "<br />Child thread started <br/>"; lblmessage.Text += "Child Thread: Coiunting to 10"; for( int i =0; i<10; i++) { Thread. Sleep(500); lblmessage.Text += "<br/> in Child thread </br>"; } lblmessage.Text += "<br/> child thread finished"; }catch(ThreadAbortException e){ lblmessage.Text += "<br /> child thread - exception"; }finally{ lblmessage.Text += "<br /> child thread - unable to catch the exception"; } } } }
當頁面被載入時,一個新的執行緒會以childthreadcall() 為參考開始啟動。主線程的活動會直接顯示在網頁上。
第二個執行緒運行並將訊息傳送到控制標籤。
在子執行緒執行時主執行緒休眠2000 毫秒。
子執行緒持續運行直到它被主執行緒中止,然後它會拋出ThreadAbortException 例外並終止。
控制返回到主線程。
執行時程式會發送以下訊息: