.NET將關於多線程的功能定義在System.Threading名稱空間中,因此,如果您的程式要使用多線程,必須引用此命名空間(using System.Threading)。
我們知道,在.NET中使用多線程有兩種方式:
1,使用Thread建立一個新的線程。
2,使用ThreadPool。
首先我們先說說和Thread有關的幾個概念。
1,建立線程和啟動線程,如果代碼可實現
Thread newThread = new Thread(new ThreadStart(Work.DoWork));
newThread.Start();
或者
Thread newThread = new Thread(new ParameterizedThreadStart(Work.DoWork));
newThread.Start(42);
ParameterizedThreadStart 此委託在 .NET Framework 2.0 版中是新增的
在建立託管的線程時,在該線程上執行的方法將通過一個傳遞給 Thread 建構函式的 ThreadStart 委託或 ParameterizedThreadStart 委託來表示。
在調用 System.Threading.Thread.Start 方法之前,該線程不會開始執行。執行將從 ThreadStart 或 ParameterizedThreadStart 委託表示的方法的第一行開始。
ParameterizedThreadStart 委託和 Thread.Start(Object) 方法重載使得將資料傳遞給線程過程變得簡單,但由於可以將任何對象傳遞給 Thread.Start(Object),因此這種方法並不是型別安全的。
將資料傳遞給線程過程的一個更可靠的方法是將線程過程和資料欄位都放入輔助對象。
下面的程式碼範例示範通過靜態方法和執行個體方法建立和使用 ParameterizedThreadStart 委託的文法,ThreadStart委託的使用方法和ParameterizedThreadStart一樣,
唯一的區別在ThreadStart封裝的方法不需要參數。(執行個體來自MSDN)
using System;
using System.Threading;
public class Work
{
public static void Main()
{
// To start a thread using a shared thread procedure, use
// the class name and method name when you create the
// ParameterizedThreadStart delegate.
//
Thread newThread = new Thread(
new ParameterizedThreadStart(Work.DoWork));
// Use the overload of the Start method that has a
// parameter of type Object. You can create an object that
// contains several pieces of data, or you can pass any
// reference type or value type. The following code passes
// the integer value 42.
//
newThread.Start(42);
// To start a thread using an instance method for the thread
// procedure, use the instance variable and method name when
// you create the ParameterizedThreadStart delegate.
//
Work w = new Work();
newThread = new Thread(
new ParameterizedThreadStart(w.DoMoreWork));
// Pass an object containing data for the thread.
//
newThread.Start("The answer.");
}
public static void DoWork(object data)
{
Console.WriteLine("Static thread procedure. Data='{0}'",
data);
}
public void DoMoreWork(object data)
{
Console.WriteLine("Instance thread procedure. Data='{0}'",
data);
}
}
/**//* This code example produces the following output (the order
of the lines might vary):
Static thread procedure. Data='42'
Instance thread procedure. Data='The answer'
*/
2,掛起線程
掛起線程分為兩種,主動掛起和被動掛起。
主動掛起可表示為:
Thread.Sleep (Int32) 或 Thread.Sleep (TimeSpan) ,表示將當前調用線程掛起指定的時間。
被動掛起表示為:
Thread newThread = new Thread(new ThreadStart(Work.DoWork));
newThread.Start();
newThread.Join();
或者
Thread.CurrentThread.Join(50);
Join表示在繼續執行標準的 COM 和 SendMessage 訊息泵處理期間,阻止調用線程,直到某個線程終止為止。
在[STAThread]指示的Com執行緒模式中,我們應該使用Thread.CurrentThread.Join(50)這種方式。有一個與之有關的樣本,
Thread.Sleep vs. Thread.CurrentThread.Join
3,終止線程
在調用 Abort 方法以銷毀線程時,公用語言運行庫將引發 ThreadAbortException。ThreadAbortException 是一種可捕獲的特殊異常,但在 catch 塊的結尾處它將自動被再次引發。
引發此異常時,運行庫將在結束線程前執行所有 finally 塊。由於線程可以在 finally 塊中執行未綁定計算,或調用 Thread.ResetAbort 來取消中止,所以不能保證線程將完全結束。
如果您希望一直等到被中止的線程結束,可以調用 Thread.Join 方法。Join 是一個模組化調用,它直到線程實際停止執行時才返回。
注意:在託管可執行檔中的所有前台線程已經結束後,當公用語言運行庫 (CLR) 停止後台線程時,它不使用 System.Threading.Thread.Abort。
因此,無法使用 ThreadAbortException 來檢測 CLR 何時終止後台線程。
下面的樣本說明如何中止線程。接收 ThreadAbortException 的線程使用 ResetAbort 方法取消中止請求並繼續執行。(樣本來自MSDN)
using System;
using System.Threading;
using System.Security.Permissions;
public class ThreadWork {
public static void DoWork() {
try {
for(int i=0; i<100; i++) {
Console.WriteLine("Thread - working.");
Thread.Sleep(100);
}
}
catch(ThreadAbortException e) {
Console.WriteLine("Thread - caught ThreadAbortException - resetting.");
Console.WriteLine("Exception message: {0}", e.Message);
Thread.ResetAbort();
}
Console.WriteLine("Thread - still alive and working.");
Thread.Sleep(1000);
Console.WriteLine("Thread - finished working.");
}
}
class ThreadAbortTest {
public static void Main() {
ThreadStart myThreadDelegate = new ThreadStart(ThreadWork.DoWork);
Thread myThread = new Thread(myThreadDelegate);
myThread.Start();
Thread.Sleep(100);
Console.WriteLine("Main - aborting my thread.");
myThread.Abort();
myThread.Join();
Console.WriteLine("Main ending.");
}
}
這段代碼產生以下輸出:
Thread - working.
Main - aborting my thread.
Thread - caught ThreadAbortException - resetting.
Exception message: Thread was being aborted.
Thread - still alive and working.
Thread - finished working.
Main ending.
最後還有一點需要說明的是,在.NET Framework 2.0後,Thread對象的Suspend和Resume方法已被擯棄。
原因在於使用 Suspend 和 Resume 方法來同步線程的活動。您無法知道掛起線程時它正在執行什麼代碼。
如果您在安全許可權評估期間掛起持有鎖的線程,則 AppDomain 中的其他線程可能被阻止。
如果您線上程正在執行類建構函式時掛起它,則 AppDomain 中試圖使用該類的其他線程將被阻止。很容易發生死結。