[C#]CLR下執行緒的基本介紹與使用
阿新 • • 發佈:2019-02-16
專用執行緒
由new Thread()建立的執行緒稱為專用執行緒。一般不建議使用專用執行緒,除非有下列情況:
- 你需要執行緒執行在非正常的優先順序時。執行緒池中的所有執行緒都是執行在正常優先順序(Normal)下。
- 你需要執行緒作為前臺執行緒執行時。執行緒池中的所有執行緒都是後臺執行緒。
- 當執行一個非常長時間的計算密集型任務時。
- 你想建立一個專用執行緒,並通過Thread.Abort能儘早地結束它的時候
//create a dedicated thread and have it call a method asynchronously private static void DedicatedThread() { Thread dedicatedThread = new Thread(ComputeBoundOp); dedicatedThread.Start(5); Console.WriteLine("Main thread: Doing other work here ..."); Thread.Sleep(8000); //Simulating other work dedicatedThread.Join();//等待執行緒終止 } private static void ComputeBoundOp(Object state) { Console.WriteLine("In ComputeBoundOp: state={0}",state); Thread.Sleep(1000); //when this method returns,the dedicated thread dies }
為什麼要使用執行緒
通常有2個原因:
- 為了能及時響應(主要針對客戶端GUI應用),也就是通常說的為了不卡介面
- 效能(針對客戶端和伺服器應用): 因為windows是每個CPU分配一個執行緒,並且是多個CPU同時執行這些執行緒,所以在多CPU的機器上使用多執行緒能提升效能
執行緒的優先順序
作業系統的每個執行緒優先順序為0-31(0為最低,31為最高)。當系統要給CPU分配執行緒時,先檢查是否有優先順序為31的,有31的則立即將執行緒分配給CPU.當CPU一直都是在執行優先順序為31的執行緒,而從來不執行0-30優先順序執行緒時,這種情況稱為執行緒的餓死。餓死是高優先順序執行緒佔用大量CPU時間導致,在多處理器的機器上很少出現餓死,因為多個處理器可以同時執行多個高優先順序的執行緒。
系統中為0優先順序執行緒的只有一個,稱為零頁執行緒(zero page thread),它是當系統啟動時,建立的一個特殊執行緒。
windows支援6種程序優先順序: 空閒、低於正常、正常、高於正常、高、實時。你應該儘可能地避免使用實時的優先順序程序,因為實時優先順序很高,可能干擾作業系統任務,如磁碟I/O等。
前臺執行緒與後臺執行緒
CLR認為每個執行緒不是前臺執行緒就是後臺執行緒。當所有的前臺執行緒停止執行時,CLR會強制關閉所有還在執行的後臺執行緒。專用執行緒預設是前臺執行緒,執行緒池的執行緒預設都是後臺執行緒。
Thead t=new Thread(worker);
t.IsBackground=true;//使執行緒作為後臺執行緒執行
執行緒池
建立和銷燬一個執行緒是比較費時的操作,而且大量的執行緒存在會浪費記憶體以及損傷效能。所以就出現了執行緒池。執行緒池為所有AppDomain所共享。
//執行緒池演示 private static void ThreadPoolDemonstrate() { Console.WriteLine("Main thread: queuing an asynchronous operation"); ThreadPool.QueueUserWorkItem(ComputeBoundOp,6); Console.WriteLine("Main thread: Doing other work here ..."); Thread.Sleep(8000); }
執行緒的執行上下文
每個執行緒都有一個執行上下文資料與其關聯。通過控制執行緒的執行上下文,可以實現某些變數只在某些執行緒中使用。
//執行緒的執行上下文
private static void ExecContext()
{
//put some data into the Main thread's logical call context
CallContext.LogicalSetData("Name", "Cryking");
//Initiate some work to be done by a thread pool thread
//The thread pool thread can access the logical call context data
ThreadPool.QueueUserWorkItem(
state=> {
Console.WriteLine("Name={0}",CallContext.LogicalGetData("Name"));
});
//Now,suppress the flowing of the Main thread's execution context
ExecutionContext.SuppressFlow();
//Initiate some work to be done by a thread pool thread
//The thread pool thread CANNOT access the logical call context data
ThreadPool.QueueUserWorkItem(
state => {
Console.WriteLine("Name={0}", CallContext.LogicalGetData("Name"));
});
//Restore the flowing of the Main thread's execution context in case
//it employs more thread pool threads in the future
ExecutionContext.RestoreFlow();
}
執行緒的取消
.NET框架提供了一個標準的執行緒取消模式。
//執行緒的取消演示
private static void CancellationDemo()
{
CancellationTokenSource cts = new CancellationTokenSource();
cts.Token.Register(() => Console.WriteLine("cancel callback operation 1 ..."));
cts.Token.Register(() => Console.WriteLine("cancel callback operation 2 ..."));
//Pass the cancellationToke and the number-to-count-to into the operation
ThreadPool.QueueUserWorkItem(o => Count(cts.Token, 1000));
Console.WriteLine("Press <Enter> to cancel the operation.");
Console.ReadLine();
cts.Cancel();//If Count returned already,Cancel has no effect on it.
}
private static void Count(CancellationToken token, int v)
{
for (int count = 0; count < v; count++)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("Count is cancelled");
break;
}
Console.WriteLine(count);
Thread.Sleep(400);
}
Console.WriteLine("Count is done");
}