進程和線程 進程是一個系統級別的概念,用來描述一組資源和程式運行所必須的記憶體分配。每一個進程都有一個唯一的進程標識符(PID);線程是進程的基本單元;進程的入口點創建的第一個線程被稱為主線程;線程主要是由CPU寄存器、調用棧和線程本地存儲器(Thread Local Storage,TLS)組成的。 ...
進程和線程
進程是一個系統級別的概念,用來描述一組資源和程式運行所必須的記憶體分配。每一個進程都有一個唯一的進程標識符(PID);線程是進程的基本單元;進程的入口點創建的第一個線程被稱為主線程;線程主要是由CPU寄存器、調用棧和線程本地存儲器(Thread Local Storage,TLS)組成的。CPU寄存器主要記錄當前所執行線程的狀態,調用棧主要用於維護線程所調用到的記憶體與數據,TLS主要用於存放線程的狀態信息。
應用程式域(AppDomain):.Net可執行程式承載在進程中的邏輯分區;一個進程可以包含多個應用程式域,每一個應用程式域中承載一個.Net可執行程式;每一個程式域都和該進程(或其它進程)中的其它的程式域完全徹底隔離開,只有使用分散式編程協議(如WCF)才能訪問其它應用程式域中的任何數據;
System.AppDomain
一個線程可以穿梭在多個應用程式域中,但在某個時刻,線程只會處於一個應用程式域內。
上下文邊界
每個線程都有自己的屬性,在每個線程的內核對象之中,都包含一個上下文結構,上下文結構的存在是為了反映線上程上一次執行時,線程CPU寄存器的狀態。在任何時刻,Windows只將一個線程代碼分配給一個CPU,一個線程允許運行一個時間片,線上程的“時間片”結束之後,Windows會檢查現有所有線程內核對象,只有那些沒有在等待什麼的線程才適合調度。Windows選擇一個可調度的線程內核對象,並且換到它。
Windows選擇一個可調度的線程有一套獨特的標準,Windows執行線程的規律和時間片沒多大的關係,線程在運行的任何時刻都可以停止,然後Windows又去調度另一個線程,你有點控制權,去控制你想運行的線程,但是這控制權不多,不控製為好。對於線程的執行,記住一點:
你不能保證自己的線程一直運行,你不能阻止其他的線程的運行。
線程優先順序別0~31,Windows把線程用從高到低的調度方式輪流調度線程,假如有一個優先順序別為31的線程運行結束了,然後Windows會找下一個空閑的線程,如果空閑的線程中有一個級別也是31的線程,那麼Windows又會把31級別的線程交給CPU處理。
進程優先順序類:
Windows支持6個進程優先順序類:Idel,Below Normal,Normal,Above Normal,Hight和Realtime(依次向高),其中Normal是預設的進程優先順序,所以它是最常用的。
Windows支持7個相對線程優先順序:Idel,Lowest,Below Normal,Normal,Above Normal,Highest和Time-Critical。
相對線程優先順序 |
進程優先順序 |
|
||||
Idle |
Below Normal |
Normal |
Above Normal |
High |
Realtime |
|
Time-critical |
15 |
15 |
15 |
15 |
15 |
31 |
Highest |
6 |
8 |
10 |
12 |
15 |
26 |
Above Normal |
5 |
7 |
9 |
11 |
14 |
25 |
Normal |
4 |
6 |
8 |
10 |
13 |
24 |
Below Normal |
3 |
5 |
7 |
9 |
12 |
23 |
Lowest |
2 |
4 |
6 |
8 |
11 |
22 |
Idle |
1 |
1 |
1 |
1 |
1 |
16 |
記住:如果更改一個進程的優先順序類,線程的相對優先順序不會改變,但它的優先值會改變。
Windows永遠都不會調度進程,他調度的只有線程,“進程優先順序類”是Microsoft提出的一個抽象概念,目的是為了幫助你理解自己的應用程式和其他正在運行的應用程式的關係,它沒有別的用途。
可以更改它的線程相對優先順序,Thread中的Priority屬性,向它傳遞ThreadPriority枚舉類型中定義的5各值之一,即在上表中的灰色部分列。
線程池ThreadPool
每個進程都有一個線程池,線程池的預設大小為:每個可用的處理器有 25 個線程。使用 SetMaxThreads 方法可以更改線程池中的線程數。
ThreadPool類型擁有一個QueueUserWorkItem的靜態方法。該靜態方法接收一個委托(WaitCallback),代表用戶自定義的一個非同步操作。
// 一個 System.Threading.WaitCallback,表示要執行的方法。
// 如果此方法成功排隊,則為 true;如果未能將該工作項排隊,則引發 System.NotSupportedException。
//System.NotSupportedException:承載公共語言運行時的宿主不支持此操作。
[SecuritySafeCritical]
public static bool QueueUserWorkItem(WaitCallback callBack); // 將方法排入隊列以便執行,並指定包含該方法所用數據的對象。此方法在有線程池線程變得可用時執行。
// System.Threading.WaitCallback,它表示要執行的方法。
// state: 包含方法所用數據的對象。
// 如果此方法成功排隊,則為 true;如果未能將該工作項排隊,則引發 System.NotSupportedException。
[SecuritySafeCritical]
public static bool QueueUserWorkItem(WaitCallback callBack, object state);
使用線程池的好處:
減少了線程的創建、開始和停止的次數,提高了效率
能夠使我們將註意力放在業務邏輯上而不是多線程架構上。
以下場景是不適合使用線程池,而是手工管理線程:
- 需要前臺線程時。因為線程池中的線程總是後臺線程。
- 需要線程具有特定的優先順序。因為放到線程池中的線程都是預設的優先順序(ThreadPriority.Normal),無法對其優先順序進行設置。
- 需要長時間運行的任務。由於線程池具有最大線程數限制,因此大量阻塞的線程池線程可能會阻止任務啟動。
- 如果需要有一個帶有固定標識的線程便於退出、掛起或通過名字發現它。
- 對於COM對象,入池的所有線程都是多線程單元(multithreaded apartment MTA)線程;許多COM對象都需要單線程單元(single-threaded apartment STA)線程;