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