天天看點

細說多線程(二)—— 線程的基礎知識

目錄

一、線程的定義

二、線程的基礎知識

三、以ThreadStart方式實作多線程

四、CLR線程池的工作者線程

五、CLR線程池的I/O線程

六、異步 SqlCommand

七、并行程式設計與PLINQ

八、計時器與鎖

2.1 System.Threading.Thread類

System.Threading.Thread是用于控制線程的基礎類,通過Thread可以控制目前應用程式域中線程的建立、挂起、停止、銷毀。

它包括以下常用公共屬性:

屬性名稱 說明
CurrentContext 擷取線程正在其中執行的目前上下文。
CurrentThread 擷取目前正在運作的線程。
ExecutionContext 擷取一個 ExecutionContext 對象,該對象包含有關目前線程的各種上下文的資訊。
IsAlive 擷取一個值,該值訓示目前線程的執行狀态。
IsBackground 擷取或設定一個值,該值訓示某個線程是否為背景線程。
IsThreadPoolThread 擷取一個值,該值訓示線程是否屬于托管線程池。
ManagedThreadId 擷取目前托管線程的唯一辨別符。
Name 擷取或設定線程的名稱。
Priority 擷取或設定一個值,該值訓示線程的排程優先級。
ThreadState 擷取一個值,該值包含目前線程的狀态。

2.1.1 線程的辨別符

ManagedThreadId 是确認線程的唯一辨別符,程式在大部分情況下都是通過Thread.ManagedThreadId來辨識線程的。而Name是一個可變值,在預設時 候,Name為一個空值 Null,開發人員可以通過程式設定線程的名稱,但這隻是一個輔助功能。

2.1.2 線程的優先級别

.NET為線程設定了Priority屬性來定義線程執行的優先級别,裡面包含5個選項,其中Normal是預設值。除非系統有特殊要求,否則不應該随便設定線程的優先級别。

成員名稱
Lowest 可以将 Thread 安排在具有任何其他優先級的線程之後。
BelowNormal 可以将 Thread 安排在具有 Normal 優先級的線程之後,在具有 Lowest 優先級的線程之前。
Normal 預設選擇。可以将 Thread 安排在具有 AboveNormal 優先級的線程之後,在具有 BelowNormal 優先級的線程之前。
AboveNormal 可以将 Thread 安排在具有 Highest 優先級的線程之後,在具有 Normal 優先級的線程之前。
Highest 可以将 Thread 安排在具有任何其他優先級的線程之前。

2.1.3 線程的狀态

通過ThreadState可以檢測線程是處于Unstarted、Sleeping、Running 等等狀态,它比 IsAlive 屬性能提供更多的特定資訊。

前面說過,一個應用程式域中可能包括多個上下文,而通過CurrentContext可以擷取線程目前的上下文。

CurrentThread是最常用的一個屬性,它是用于擷取目前運作的線程。

2.1.4 System.Threading.Thread的方法

Thread 中包括了多個方法來控制線程的建立、挂起、停止、銷毀,以後來的例子中會經常使用。

方法名稱
Abort()     終止本線程。
GetDomain() 傳回目前線程正在其中運作的目前域。
GetDomainId() 傳回目前線程正在其中運作的目前域Id。
Interrupt() 中斷處于 WaitSleepJoin 線程狀态的線程。
Join() 已重載。 阻塞調用線程,直到某個線程終止時為止。
Resume() 繼續運作已挂起的線程。
Start()   執行本線程。
Suspend() 挂起目前線程,如果目前線程已屬于挂起狀态則此不起作用
Sleep()   把正在運作的線程挂起一段時間。

2.1.5 開發執行個體

以下這個例子,就是通過Thread顯示目前線程資訊

1         static void Main(string[] args)
 2         {
 3             Thread thread = Thread.CurrentThread;
 4             thread.Name = "Main Thread";
 5             string threadMessage = string.Format("Thread ID:{0}\n    Current AppDomainId:{1}\n    "+
 6                 "Current ContextId:{2}\n    Thread Name:{3}\n    "+
 7                 "Thread State:{4}\n    Thread Priority:{5}\n",
 8                 thread.ManagedThreadId, Thread.GetDomainID(), Thread.CurrentContext.ContextID,
 9                 thread.Name, thread.ThreadState, thread.Priority);
10             Console.WriteLine(threadMessage);
11             Console.ReadKey();
12         }      

運作結果

細說多線程(二)—— 線程的基礎知識

2.2  System.Threading 命名空間

在 System.Threading命名空間内提供多個方法來建構多線程應用程式,其中ThreadPool與Thread是多線程開發中最常用到的, 在.NET中專門設定了一個CLR線程池專門用于管理線程的運作,這個CLR線程池正是通過ThreadPool類來管理。而Thread是管理線程的最 直接方式,下面幾節将詳細介紹有關内容。

類    
AutoResetEvent 通知正在等待的線程已發生事件。無法繼承此類。
管理目前線程的執行上下文。無法繼承此類。
Interlocked 為多個線程共享的變量提供原子操作。
Monitor 提供同步對對象的通路的機制。
Mutex 一個同步基元,也可用于程序間同步。
Thread 建立并控制線程,設定其優先級并擷取其狀态。
ThreadAbortException 在對 Abort 方法進行調用時引發的異常。無法繼承此類。
ThreadPool 提供一個線程池,該線程池可用于發送工作項、處理異步 I/O、代表其他線程等待以及處理計時器。
Timeout 包含用于指定無限長的時間的常數。無法繼承此類。
Timer 提供以指定的時間間隔執行方法的機制。無法繼承此類。
WaitHandle 封裝等待對共享資源的獨占通路的作業系統特定的對象。

在System.Threading中的包含了下表中的多個常用委托,其中ThreadStart、ParameterizedThreadStart是最常用到的委托。

由ThreadStart生成的線程是最直接的方式,但由ThreadStart所生成并不受線程池管理。

而ParameterizedThreadStart是為異步觸發帶參數的方法而設的,在下一節将為大家逐一細說。

委托
ContextCallback 表示要在新上下文中調用的方法。
ParameterizedThreadStart 表示在 Thread 上執行的方法。
ThreadExceptionEventHandler 表示将要處理 Application 的 ThreadException 事件的方法。
ThreadStart
TimerCallback 表示處理來自 Timer 的調用的方法。
WaitCallback 表示線程池線程要執行的回調方法。
WaitOrTimerCallback 表示當 WaitHandle 逾時或終止時要調用的方法。

2.3 線程的管理方式

通 過ThreadStart來建立一個新線程是最直接的方法,但這樣建立出來的線程比較難管理,如果建立過多的線程反而會讓系統的性能下載下傳。有見及 此,.NET為線程管理專門設定了一個CLR線程池,使用CLR線程池系統可以更合理地管理線程的使用。所有請求的服務都能運作于線程池中,當運作結束時 線程便會回歸到線程池。通過設定,能控制線程池的最大線程數量,在請求超出線程最大值時,線程池能按照操作的優先級别來執行,讓部分操作處于等待狀态,待 有線程回歸時再執行操作。