多線程
一個線程被定義為一個程序的執行路徑。每個線程都定義了一個獨特的流量控制。如果你的應用程序涉及到復雜的和耗時的操作,如數據庫訪問或一些激烈的 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.jfrwli.cn/uploads/allimg/tsqont514bc" > <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 ThreadStart(childthreadcall); Response.Write("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 異常并被終止。
- 控制返回到主線程。
- 當執行時程序會發送以下信息: