線程被定義為程序的執(zhí)行路徑。每個線程都定義了一個獨特的控制流程。如果應(yīng)用程序涉及復(fù)雜和耗時的操作,那么設(shè)置不同的執(zhí)行路徑或線程通常有助于每個線程執(zhí)行特定的作業(yè)。
線程是輕量級的進程。使用線程的一個常見示例是通過現(xiàn)代操作系統(tǒng)實現(xiàn)并發(fā)編程。使用線程節(jié)省了CPU周期并提高了應(yīng)用程序的效率。
到目前為止,我們編寫了單個線程作為單個進程運行的程序,它是應(yīng)用程序的運行實例。 但是,這樣應(yīng)用程序可以一次執(zhí)行一個作業(yè)。為了使它一次執(zhí)行多個任務(wù),它可以分為較小的線程。
當創(chuàng)建System.Threading.Thread類的對象時,線程的生命周期將會啟動,當線程終止或完成執(zhí)行時,該循環(huán)將結(jié)束。
以下是線程生命周期中的各種狀態(tài):
Start方法的情況。Sleep方法已被調(diào)用Wait方法已被調(diào)用在 C# 中,System.Threading.Thread類用于處理線程。它允許在多線程應(yīng)用程序中創(chuàng)建和訪問單個線程。在進程中執(zhí)行的第一個線程稱為主線程。
當 C# 程序開始執(zhí)行時,主線程就會被自動創(chuàng)建。使用Thread類創(chuàng)建的線程稱為主線程的子線程。可以使用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();
}
}
}
當上述代碼被編譯并執(zhí)行時,它產(chǎn)生以下結(jié)果:
This is MainThread
下表顯示了Thread類的一些最常用的屬性:
| 屬性 | 描述 |
|---|---|
| CurrentContext | 獲取當前正在執(zhí)行的線程的上下文。 |
| CurrentCulture | 獲取或設(shè)置當前線程的文化(culture)。 |
| CurrentPrinciple | 獲取或設(shè)置線程的當前主體(用于基于角色的安全性)。 |
| CurrentThread | 獲取當前正在運行的線程。 |
| CurrentUICulture | 獲取或設(shè)置資源管理器使用的當前文化(culture),以便在運行時查找特定于文化的資源。 |
| ExecutionContext | 獲取一個ExecutionContext對象,該對象包含有關(guān)當前線程的各種上下文的信息。 |
| IsAlive | 獲取指示當前線程的執(zhí)行狀態(tài)的值。 |
| IsBackground | 獲取或設(shè)置一個值,指示線程是否是后臺線程。 |
| IsThreadPoolThread | 獲取一個值,指示線程是否屬于托管線程池。 |
| ManagedThreadId | 獲取當前受管線程的唯一標識符。 |
| Name | 獲取或設(shè)置線程的名稱。 |
| Priority | 獲取或設(shè)置一個指示線程的調(diào)度優(yōu)先級的值。 |
| ThreadState | 獲取包含當前線程的狀態(tài)的值。 |
下表顯示了Thread類最常用的一些方法:
| 序號 | 方法 | 描述 |
|---|---|---|
| 1 | public void Abort() |
在調(diào)用它的線程中引發(fā)ThreadAbortException異常,以開始終止線程的進程。調(diào)用此方法通常會終止線程。 |
| 2 | public static LocalDataStoreSlot AllocateDataSlot() |
在所有線程上分配一個未命名的數(shù)據(jù)槽。為了獲得更好的性能,請使用標記為ThreadStaticAttribute屬性的字段。 |
| 3 | public static LocalDataStoreSlot AllocateNamedDataSlot(string name) |
在所有線程上分配一個命名的數(shù)據(jù)槽。為了獲得更好的性能,請使用標記為ThreadStaticAttribute屬性的字段。 |
| 4 | public static void BeginCriticalRegion() |
通知主機執(zhí)行即將進入的代碼區(qū)域,線程中止或未處理的異常的影響可能會危及應(yīng)用程序域中的其他任務(wù)。 |
| 5 | public static void BeginThreadAffinity() |
通知托管代碼即將執(zhí)行依賴于當前物理操作系統(tǒng)線程標識的指令。 |
| 6 | public static void EndCriticalRegion() |
通知主機即將執(zhí)行即將進入的代碼區(qū)域,線程中止或未處理異常的影響限于當前任務(wù)。 |
| 7 | public static void EndThreadAffinity() |
通知托管代碼已完成執(zhí)行依賴于當前物理操作系統(tǒng)線程標識的指令的主機。 |
| 8 | public static void FreeNamedDataSlot(string name) |
消除進程中所有線程的名稱和插槽之間的關(guān)聯(lián)。為了獲得更好的性能,請使用標記為ThreadStaticAttribute屬性的字段。 |
| 9 | public static Object GetData(LocalDataStoreSlot slot) |
從當前線程的當前域中指定插槽中檢索值。為了獲得更好的性能,請使用標記為ThreadStaticAttribute屬性的字段。 |
| 10 | public static AppDomain GetDomain() |
返回當前線程正在運行的當前域。 |
| 11 | public static AppDomain GetDomainID() |
返回唯一的應(yīng)用程序域標識符 |
| 12 | public static LocalDataStoreSlot GetNamedDataSlot(string name) |
查找一個命名的數(shù)據(jù)槽。為了獲得更好的性能,請使用標記為ThreadStaticAttribute屬性的字段。 |
| 13 | public void Interrupt() |
中斷處于WaitSleepJoin線程狀態(tài)的線程。 |
| 14 | public void Join() |
阻止調(diào)用線程直到線程終止,同時繼續(xù)執(zhí)行標準COM和SendMessage抽取。此方法具有不同的重載形式。 |
| 15 | public static void MemoryBarrier() |
同步存儲器訪問如下:執(zhí)行當前線程的處理器無法重新排序指令,使得在調(diào)用MemoryBarrier之前進行的存儲器訪問在內(nèi)存訪問之后執(zhí)行,這些內(nèi)存訪問之后對MemoryBarrier的調(diào)用。 |
| 16 | public static void ResetAbort() |
取消當前線程中止請求。 |
| 17 | public static void SetData(LocalDataStoreSlot slot, Object data) |
為當前正在運行的線程的當前域設(shè)置指定槽中的數(shù)據(jù)。為了獲得更好的性能,請改用標記為ThreadStaticAttribute屬性的字段。 |
| 18 | public void Start() |
開始一個線程 |
| 19 | public static void Sleep(int millisecondsTimeout) |
使線程暫停一段時間 |
| 20 | public static void SpinWait(int iterations) |
使線程等待iterations參數(shù)定義的次數(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)。此方法具有不同的重載形式。上面只給出了幾個。 |
| 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) |
立即將值寫入字段,以便該值對計算機中的所有處理器可見。此方法具有不同的重載形式。上面只給出了幾個。 |
| 23 | public static bool Yield() |
使調(diào)用線程對另一個準備在當前處理器上運行的線程執(zhí)行執(zhí)行。操作系統(tǒng)選擇要產(chǎn)生的線程。 |
實現(xiàn)線程是通過擴展Thread類創(chuàng)建的。擴展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();
}
}
}
當上述代碼被編譯并執(zhí)行時,它產(chǎn)生以下結(jié)果:
In Main: Creating the Child thread
Child thread starts
Thread類提供了各種管理線程的方法。
以下示例演示了如何使用sleep()方法在特定時間段內(nèi)暫停線程。
using System;
using System.Threading;
namespace MultithreadingApplication
{
class ThreadCreationProgram
{
public static void CallToChildThread()
{
Console.WriteLine("Child thread starts");
// the thread is paused for 5000 milliseconds
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();
}
}
}
當上述代碼被編譯并執(zhí)行時,它產(chǎn)生以下結(jié)果:
In Main: Creating the Child thread
Child thread starts
Child Thread Paused for 5 seconds
Child thread resumes
Abort()方法用于銷毀線程。運行時通過拋出ThreadAbortException來中止線程。這個異常不能被捕獲,控件發(fā)送到finally塊(如果有的話)。
以下一個實現(xiàn)線程的程序:
using System;
using System.Threading;
namespace MultithreadingApplication
{
class ThreadCreationProgram
{
public static void CallToChildThread()
{
try
{
Console.WriteLine("Child thread starts");
// do some work, like counting to 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();
//stop the main thread for some time
Thread.Sleep(2000);
//now abort the child
Console.WriteLine("In Main: Aborting the Child thread");
childThread.Abort();
Console.ReadKey();
}
}
}
當上述代碼被編譯并執(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