多線程編程是跨語言的,跨環境的,所以我們得學好它,對應用程序的性能提高是有幫助的。
Thread類的使用
1.1 啓動新的線程
Thread thread = new Thread(new ThreadStart(Count));Count是要被新的線程執行的函數,這個函數默認情況下是沒有參數的。
1.2 殺死線程
在殺死一個線程前,先判斷這個線程是否還活着(用IsAlive屬性),如果它已經死掉了,就不要在殺死它了,那就成鞭屍了沒有用的,如果它活着調用ABort方法來殺死此線程。
1.3 暫停線程
讓一個運行的線程暫時停止運行即讓一個正常運行的線程休眠一段時間,如:thread.sheep(1000)即讓此線程休眠1秒鐘。
1.4 優先級
每個線程是不一樣的,它有優先級的,Thread 類中的ThreadPriority屬性用來設置優先級,但是不能保證操作系統會接受此優先級,一個線程的優先級分爲五種,Normal(正常的),AboveNormal(超過正常的),BelowNormal(低於正常的),Highest(最高的),Lowest(最低的)。
1.5 掛起線程
掛起線程是整個線程暫時停止了,掛起線程的整個暫停和暫停一個線程不一樣,暫停一個線程是讓一個正常運行的線程休眠一段時間,而掛起線程是把機子掛起來了,Thread類的Suspend方法用來掛起線程,直到調用Resume,此線程才能繼續執行,如果線程被掛起了,當然就不會起作用了。
舉個例子
比如你要抄臘肉,暫停線程相當於休息一會再炒臘肉,掛起線程就是把臘肉掛到牆上了,沒得抄了,恢復線程相當於把牆上的臘肉拿下來炒了。
1.6 恢復線程
Resume用來恢復已經掛起的線程,讓它繼續執行,如果線程沒被掛起,當然也不會起作用了。
舉個例子
比如我控制5個機器人去探索月球,每個機器人相當於一個線程,每個機器人頭上有4個按鈕(啓動新的線程,暫停線程,掛起線程,恢復線程),我按一下啓動新的線程按鈕,這個機器人就開始工作了,我按一下暫停線程,機器人就停止工作了,這5個機器人相當於5個線程,同時併發執行探索月球的,你可以通過每個機器人頭上的按鈕,同時控制這5個機器人也相當於同時控制5個線程了。
Thread
一個線程的方法是不帶任何參數的,同時也不返回任何值的,它的命名規則和一般方法一樣,可以是靜態方法,也可以是非靜態的方法,當這個方法執行完畢後,相應的線程也就結束了,這個線程的IsAlive屬性也就被設置爲flase了。
.NET的公共語言運行時(CLR)能區分兩種不同類型的線程:即前臺線程和後臺線程,兩者的區別是前臺線程是應用程序必須運行完所有的前臺線程才能退出,而對於後臺線程而言,應用程序不考慮其是否已經運行完畢而直接退出,所有的後臺線程在應用程序退出後,就都自動結束了。
默認情況下都是前臺線程 IsBackground = false。
實現步驟
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace _1_ThreadClassExample
{
class Program
{
public static void ThreadProcess()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("ThreadProcess: {0}", i);
Thread.Sleep(0);//線程被阻塞的毫秒數,爲0表示應掛起此線程以便其他等待線程能夠執行
}
}
static void Main(string[] args)
{
Console.WriteLine("在主進程中啓動一個線程");
Thread thread = new Thread(new ThreadStart(ThreadProcess));//創建一個線程
thread.Start();//啓動此線程
Thread thread2 = new Thread(new ThreadStart(ThreadProcess));//創建一個線程
thread2.Start();//啓動此線程
thread2.Suspend();//掛起此線程
for (int i = 0; i < 4; i++)
{
Console.WriteLine("主進程輸出.....");
Thread.Sleep(0);//阻塞當前的主進程,執行別的進程,線程被阻塞的毫秒數,爲0表示應掛起此線程以便其他等待線程能夠執行
}
Console.WriteLine("主線程調用線程Join方法直到ThreadProcess1線程結束");
thread.Join();///阻塞調用線程,直到某個線程終止時爲止
Console.WriteLine("ThreadProcess1線程結束");
thread2.Resume();//恢復掛起的線程
//thread2.IsBackground = true;
}
}
}
運行機制
在最開始輸出了“主進程輸出.....”,緊跟着輸出了“ThreadProcess:1” ,又接着輸出了“主進程輸出.....”,然後緊跟着是“ThreadProcess:2””,又接着輸出了“主進程輸出.....”,然後緊跟着是“ThreadProcess:3””,它們交替出現,這是因爲在for (int i = 0; i < 4; i++)中有句Thread.Sleep(0);的緣故,它的意思阻塞當前的主進程也就是Main這個主線程,執行別的進程,這個別的進程指的是thread這個進程也就是ThreadProcess()這個函數,在ThreadProcess()這個函數中也有句Thread.Sleep(0);它的意思同樣也是阻塞當前的進程也就是thread這個進程,執行別的進程,這裏別的線程指的是Main這個主線程,所以它倆交替出現,因爲thread2這個線程被掛起了,所以暫時是不會執行的,因爲這個線程(臘腸)被掛到牆上了,只有我們恢復這個線程(也就是從牆上取下這個臘腸才能炒它),這個線程纔會執行的,thread.Join();的意思是阻塞調用線程,直到某個線程終止時爲止,什麼意思呢就是阻塞當前的主線程就是Main這個主線程,直到調用的線程也就是thread這個線程執行完畢,所以你會看到連着輸出了“ThreadProcess:1”,“ThreadProcess:2”,,“ThreadProcess:3”等等直到,“ThreadProcess:9”,結束,緊接着我們寫句thread2.Resume();恢復掛起的thread2這個線程,因爲thread2這個線程執行的也是ThreadProcess()這個函數,所以最後你會看到連着輸出了“ThreadProcess:1”,“ThreadProcess:2”,,“ThreadProcess:3”等等直到,“ThreadProcess:9”,結束。最後我們取消 thread2.IsBackground = true;這句代碼的註釋,雖然我們恢復了thread2這個線程,但是因爲thread2.IsBackground = true,所以主線程不等它執行完畢就結束了,就沒有繼續輸出“ThreadProcess:1”,“ThreadProcess:2”,,“ThreadProcess:3”等等直到9。
運行效果