1. 程式人生 > >Thread類

Thread類

join 規則 完成後 receive complete let dma started I/O

  Thread類相對於線程池中的線程,使用者有更多的控制權。該類允許創建前臺線程,設置線程優先級等。Thread類的構造函數重載為接受ThreadStart和ParameterizedThreadStart類型的委托參數。

1、給線程傳遞數據

  給線程傳遞數據的兩種方式:

  1.使用帶ParameterizedThreadStart委托參數的Thread構造函數:

//定義一個數據類型,傳遞給線程
public struct Data
{
    public string Message;
}
//創建一個方法,將方法給線程的ParameterizedThreadStart委托
static
void ThreadMainWithParameters(object obj) { Data d = (Data)obj; Console.WriteLine("Running in a thread, received {0}", d.Message); } static void Main() { Data d = new Data { Message = "Info" };//創建一個數據實例 Thread t2 = new Thread(ThreadMainWithParameters);//創建線程 t2.Start(d);//啟動線程,並傳遞參數 }

  2.自定義一個類,把線程的方法定義為實例方法,然後初始化實例的數據後啟動線程。

//定義一個類,用於存放線程需要的數據和線程啟動的方法
public class MyThread
{
    private string data;//線程數據

    public MyThread(string data)
    {
        this.data = data;
    }
    //線程啟動方法
    public void ThreadMain()
    {
        Console.WriteLine("Running in a thread, data: {0}", data);
    }
}
static void Main() { MyThread obj = new MyThread("info");//創建實例信息 Thread t3 = new Thread(obj.ThreadMain);//啟動實例方法 t3.Start(); }

2、後臺線程

  如果應用程序內有任何一個前臺線程在運行,那麽應用程序就在運行。Thread類創建的線程默認時前臺線程,線程池中創建的線程是後臺線程。在使用Thread類創建線程時,可以設置IsBackground屬性,以設置創建的Thread線程時後臺線程還是前臺線程。例如:

//創建線程方法,以在主線程中調用
static void ThreadMain()
{
    Console.WriteLine("Thread {0} started", Thread.CurrentThread.Name);
    Thread.Sleep(3000);
    Console.WriteLine("Thread {0} completed", Thread.CurrentThread.Name);
}
static void Main()
{
    Thread t1 = new Thread(ThreadMain);
t1.Name = "MyNewThread"; t1.Start();
   Thread.Sleep(100); Console.WriteLine(
"Main thread ending now..."); /*******************輸出********************
* Thread MyNewThread started * Main thread ending now... * Thread MyNewThread completed * ****************************************
*/ }

  可以看到,主線程先完成任務。但是主線程內啟動的新線程是前臺線程(默認),導致主線程結束任務後,新線程仍在寫入控制臺輸出。如果在線程啟動前,將線程的IsBackground屬性設置為true,主線程結束時,會終止新線程的執行(不論是否完成任務)。

static void Main()
{
    Thread t1 = new Thread(ThreadMain);
    t1.Name = "MyNewThread";
    t1.IsBackground = true;
    t1.Start();
    Thread.Sleep(100);
    Console.WriteLine("Main thread ending now...");
    /*******************輸出********************
     *          Thread MyNewThread started
     *          Main thread ending now...
     * *****************************************/
}

  後臺線程適合用於完成後臺任務。

3、線程的優先級

  線程由操作系統調度。給線程指定優先級,將影響線程調度順序。優先級越高的線程,將會得到系統優先調度在CPU上運行。如果線程在等待資源,它就會停止運行,並釋放CPU。

  線程必須等待的可能原因:響應睡眠指令、等待磁盤I/O完成、等待網絡包到達等。如果線程不主動釋放CPU,線程調度器就會搶占該線程。線程由一個時間量,它可以持續使用CPU,直到時間到達(如果沒有更高優先級的線程時)。如果優先級相同的多個線程等待CPU,線程調度器會使用一個循環調度原則,將CPU逐一交個線程使用。如果線程被其他線程搶占,那麽它會排隊到最後去。

  只有優先級相同的多個線程同時在運行時,才能用上時間量循環規則。優先級是動態的:如果線程是CPU密集型,一直需要CPU,而且不等待資源,其優先級就降低為用該線程定義的基本優先級;如果線程在等待資源,它的優先級會提高。由於優先級的提高,所以線程可能在下一等待結束時獲得CPU。

  線程的Priority屬性,可以設置線程的優先級。線程指定優先級時,可能降低其他線程的運行概率。所以,可以根據需要短暫改變優先級。

4、控制線程

  調用Thread對象的Start()方法可以創建線程。但是,新線程並不是出於Running狀態,而是Unstarted狀態。當線程調度器調用線程時,線程則會改為Running狀態。其ThreadState屬性可以獲得線程的狀態。

  線程類的靜態方法Sleep(),會使線程處於WaitSleepJoin狀態,在等待一段時間後,線程將再次被喚醒。

  如果要停止一個線程,可以調用方法Abort()。調用該方法,會在接到終止命令的線程中拋出ThreadAbortException類型異常。捕獲該異常,可以在線程結束前做一些清理工作。如果再調用方法ResetAbort(),可能有機會再收到異常後繼續運行。如果線程沒有重置,接收到終止請求的線程的狀態就從AbortRequested改為Aborted。

  調用Join()方法可以等待線程的結束。該方法會停止當前線程,並把它設置為WaitSleepJoin狀態,直到加入的線程完成。

Thread類