線程 被定義為程序的執(zhí)行路徑。每個線程都定義了一個獨特的控制流。如果您的應(yīng)用程序涉及到復(fù)雜的和耗時的操作,那么設(shè)置不同的線程執(zhí)行路徑往往是有益的,每個線程執(zhí)行特定的工作。
線程是輕量級進(jìn)程。一個使用線程的常見實例是現(xiàn)代操作系統(tǒng)中并行編程的實現(xiàn)。使用線程節(jié)省了 CPU 周期的浪費,同時提高了應(yīng)用程序的效率。
到目前為止我們編寫的程序是一個單線程作為應(yīng)用程序的運行實例的單一的過程運行的。但是,這樣子應(yīng)用程序同時只能執(zhí)行一個任務(wù)。為了同時執(zhí)行多個任務(wù),它可以被劃分為更小的線程。
線程生命周期開始于 System.Threading.Thread 類的對象被創(chuàng)建時,結(jié)束于線程被終止或完成執(zhí)行時。
下面列出了線程生命周期中的各種狀態(tài):
在 C# 中,System.Threading.Thread 類用于線程的工作。它允許創(chuàng)建并訪問多線程應(yīng)用程序中的單個線程。進(jìn)程中第一個被執(zhí)行的線程稱為主線程。
當(dāng) C# 程序開始執(zhí)行時,主線程自動創(chuàng)建。使用 Thread 類創(chuàng)建的線程被主線程的子線程調(diào)用。您可以使用 Thread 類的 CurrentThread 屬性訪問線程。
下面的程序演示了主線程的執(zhí)行:
using System;
using System.Threading;
namespace MultithreadingApplication{
class MainThreadProgram{
static void Main(string[] args){
Thread th = Thread.CurrentThread;
th.Name = "MainThread";
Console.WriteLine("This is {0}", th.Name);
Console.ReadKey();
}
}
}
當(dāng)上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
This is MainThread
下表列出了 Thread 類的一些常用的 屬性:
屬性 | 描述 |
---|---|
CurrentContext | 獲取線程正在其中執(zhí)行的當(dāng)前上下文。 |
CurrentCulture | 獲取或設(shè)置當(dāng)前線程的區(qū)域性。 |
CurrentPrinciple | 獲取或設(shè)置線程的當(dāng)前負(fù)責(zé)人(對基于角色的安全性而言)。 |
CurrentThread | 獲取當(dāng)前正在運行的線程。 |
CurrentUICulture | 獲取或設(shè)置資源管理器使用的當(dāng)前區(qū)域性以便在運行時查找區(qū)域性特定的資源。 |
ExecutionContext | 獲取一個 ExecutionContext 對象,該對象包含有關(guān)當(dāng)前線程的各種上下文的信息。 |
IsAlive | 獲取一個值,該值指示當(dāng)前線程的執(zhí)行狀態(tài)。 |
IsBackground | 獲取或設(shè)置一個值,該值指示某個線程是否為后臺線程。 |
IsThreadPoolThread | 獲取一個值,該值指示線程是否屬于托管線程池。 |
ManagedThreadId | 獲取當(dāng)前托管線程的唯一標(biāo)識符。 |
Name | 獲取或設(shè)置線程的名稱。 |
Priority | 獲取或設(shè)置一個值,該值指示線程的調(diào)度優(yōu)先級。 |
ThreadState | 獲取一個值,該值包含當(dāng)前線程的狀態(tài)。 |
下表列出了 Thread 類的一些常用的 方法:
序號 | 方法名 & 描述 |
---|---|
1 | public void Abort()
在調(diào)用此方法的線程上引發(fā) ThreadAbortException,以開始終止此線程的過程。調(diào)用此方法通常會終止線程。 |
2 | public static LocalDataStoreSlot AllocateDataSlot()
在所有的線程上分配未命名的數(shù)據(jù)槽。為了獲得更好的性能,請改用以 ThreadStaticAttribute 屬性標(biāo)記的字段。 |
3 | public static LocalDataStoreSlot AllocateNamedDataSlot( string name)
在所有線程上分配已命名的數(shù)據(jù)槽。為了獲得更好的性能,請改用以 ThreadStaticAttribute 屬性標(biāo)記的字段。 |
4 | public static void BeginCriticalRegion()
通知主機(jī)執(zhí)行將要進(jìn)入一個代碼區(qū)域,在該代碼區(qū)域內(nèi)線程中止或未經(jīng)處理的異常的影響可能會危害應(yīng)用程序域中的其他任務(wù)。 |
5 | public static void BeginThreadAffinity()
通知主機(jī)托管代碼將要執(zhí)行依賴于當(dāng)前物理操作系統(tǒng)線程的標(biāo)識的指令。 |
6 | public static void EndCriticalRegion()
通知主機(jī)執(zhí)行將要進(jìn)入一個代碼區(qū)域,在該代碼區(qū)域內(nèi)線程中止或未經(jīng)處理的異常僅影響當(dāng)前任務(wù)。 |
7 | public static void EndThreadAffinity()
通知主機(jī)托管代碼已執(zhí)行完依賴于當(dāng)前物理操作系統(tǒng)線程的標(biāo)識的指令。 |
8 | public static void FreeNamedDataSlot(string name)
為進(jìn)程中的所有線程消除名稱與槽之間的關(guān)聯(lián)。為了獲得更好的性能,請改用以 ThreadStaticAttribute 屬性標(biāo)記的字段。 |
9 | public static Object GetData( LocalDataStoreSlot slot )
在當(dāng)前線程的當(dāng)前域中從當(dāng)前線程上指定的槽中檢索值。為了獲得更好的性能,請改用以 ThreadStaticAttribute 屬性標(biāo)記的字段。 |
10 | public static AppDomain GetDomain()
返回當(dāng)前線程正在其中運行的當(dāng)前域。 |
11 | public static AppDomain GetDomainID()
返回唯一的應(yīng)用程序域標(biāo)識符。 |
12 | public static LocalDataStoreSlot GetNamedDataSlot( string name )
查找已命名的數(shù)據(jù)槽。為了獲得更好的性能,請改用以 ThreadStaticAttribute 屬性標(biāo)記的字段。 |
13 | public void Interrupt()
中斷處于 WaitSleepJoin 線程狀態(tài)的線程。 |
14 | public void Join()
在繼續(xù)執(zhí)行標(biāo)準(zhǔn)的 COM 和 SendMessage 消息泵處理期間,阻塞調(diào)用線程,直到某個線程終止為止。此方法有不同的重載形式。 |
15 | public static void MemoryBarrier()
按如下方式同步內(nèi)存存?。簣?zhí)行當(dāng)前線程的處理器在對指令重新排序時,不能采用先執(zhí)行 MemoryBarrier 調(diào)用之后的內(nèi)存存取,再執(zhí)行 MemoryBarrier 調(diào)用之前的內(nèi)存存取的方式。 |
16 | public static void ResetAbort()
取消為當(dāng)前線程請求的 Abort。 |
17 | public static void SetData( LocalDataStoreSlot slot, Object data )
在當(dāng)前正在運行的線程上為此線程的當(dāng)前域在指定槽中設(shè)置數(shù)據(jù)。為了獲得更好的性能,請改用以 ThreadStaticAttribute 屬性標(biāo)記的字段。 |
18 | public void Start()
開始一個線程。 |
19 | public static void Sleep( int millisecondsTimeout )
讓線程暫停一段時間。 |
20 | public static void SpinWait( int iterations )
導(dǎo)致線程等待由 iterations 參數(shù)定義的時間量。 |
21 | public static byte VolatileRead( ref byte address ) public static double VolatileRead( ref double address ) public static int VolatileRead( ref int address ) public static Object VolatileRead( ref Object address ) 讀取字段值。無論處理器的數(shù)目或處理器緩存的狀態(tài)如何,該值都是由計算機(jī)的任何處理器寫入的最新值。此方法有不同的重載形式。這里只給出了一些形式。 |
22 | public static void VolatileWrite( ref byte address, byte value ) public static void VolatileWrite( ref double address, double value ) public static void VolatileWrite( ref int address, int value ) public static void VolatileWrite( ref Object address, Object value ) 立即向字段寫入一個值,以使該值對計算機(jī)中的所有處理器都可見。此方法有不同的重載形式。這里只給出了一些形式。 |
23 | public static bool Yield()
導(dǎo)致調(diào)用線程執(zhí)行準(zhǔn)備好在當(dāng)前處理器上運行的另一個線程。由操作系統(tǒng)選擇要執(zhí)行的線程。 |
線程是通過擴(kuò)展 Thread 類創(chuàng)建的。擴(kuò)展的 Thread 類調(diào)用 Start() 方法來開始子線程的執(zhí)行。
下面的程序演示了這個概念:
using System;
using System.Threading;
namespace MultithreadingApplication{
class ThreadCreationProgram{
public static void CallToChildThread(){
Console.WriteLine("Child thread starts");
}
static void Main(string[] args){
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Creating the Child thread");
Thread childThread = new Thread(childref);
childThread.Start();
Console.ReadKey();
}
}
}
當(dāng)上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
In Main: Creating the Child thread
Child thread starts
Thread 類提供了各種管理線程的方法。
下面的實例演示了 sleep() 方法的使用,用于在一個特定的時間暫停線程。
using System;
using System.Threading;
namespace MultithreadingApplication{
class ThreadCreationProgram{
public static void CallToChildThread(){
Console.WriteLine("Child thread starts");
// 線程暫停 5000 毫秒
int sleepfor = 5000;
Console.WriteLine("Child Thread Paused for {0} seconds",
sleepfor / 1000);
Thread.Sleep(sleepfor);
Console.WriteLine("Child thread resumes");
}
static void Main(string[] args){
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Creating the Child thread");
Thread childThread = new Thread(childref);
childThread.Start();
Console.ReadKey();
}
}
}
當(dāng)上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
In Main: Creating the Child thread
Child thread starts
Child Thread Paused for 5 seconds
Child thread resumes
Abort() 方法用于銷毀線程。
通過拋出 threadabortexception 在運行時中止線程。這個異常不能被捕獲,如果有 finally 塊,控制會被送至 finally 塊。
下面的程序說明了這點:
using System;
using System.Threading;
namespace MultithreadingApplication{
class ThreadCreationProgram{
public static void CallToChildThread(){
try{
Console.WriteLine("Child thread starts");
// 計數(shù)到 10
for (int counter = 0; counter <= 10; counter++){
Thread.Sleep(500);
Console.WriteLine(counter);
}
Console.WriteLine("Child Thread Completed");
}
catch (ThreadAbortException e){
Console.WriteLine("Thread Abort Exception");
}
finally{
Console.WriteLine("Couldn't catch the Thread Exception");
}
}
static void Main(string[] args){
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Creating the Child thread");
Thread childThread = new Thread(childref);
childThread.Start();
// 停止主線程一段時間
Thread.Sleep(2000); // 現(xiàn)在中止子線程
Console.WriteLine("In Main: Aborting the Child thread");
childThread.Abort();
Console.ReadKey();
}
}
}
當(dāng)上面的代碼被編譯和執(zhí)行時,它會產(chǎn)生下列結(jié)果:
In Main: Creating the Child thread
Child thread starts
0
1
2
In Main: Aborting the Child thread
Thread Abort Exception
Couldn't catch the Thread Exception
更多建議: