天天看點

C#多線程之Thread

      .NET将關于多線程的功能定義在System.Threading名稱空間中,是以,如果您的程式要使用多線程,必須引用此命名空間(using System.Threading)。 我們知道,在.NET中使用多線程有兩種方式:

1,使用Thread建立一個新的線程。

2,使用ThreadPool。

    首先我們先說說和Thread有關的幾個概念。

1. 建立線程和啟動線程,如果代碼可實作

Thread newThread = new Thread(new ThreadStart(Work.DoWork));

newThread.Start();

或者

Thread newThread = new Thread(new ParameterizedThreadStart(Work.DoWork));

newThread.Start(42);

      ParameterizedThreadStart 此委托在 .NET Framework 2.0 版中是新增的。在建立托管的線程時,在該線程上執行的方法将通過一個傳遞給 Thread 構造函數的 ThreadStart 委托或 ParameterizedThreadStart 委托來表示。在調用 System.Threading.Thread.Start 方法之前,該線程不會開始執行。執行将從 ThreadStart 或 ParameterizedThreadStart 委托表示的方法的第一行開始。ParameterizedThreadStart 委托和 Thread.Start(Object) 方法重載使得将資料傳遞給線程過程變得簡單,但由于可以将任何對象傳遞給 Thread.Start(Object),是以這種方法并不是類型安全的。将資料傳遞給線程過程的一個更可靠的方法是将線程過程和資料字段都放入輔助對象。

      下面的代碼示例示範通過靜态方法和執行個體方法建立和使用 ParameterizedThreadStart 委托的文法,ThreadStart委托的使用方法和ParameterizedThreadStart一樣,唯一的差別在ThreadStart封裝的方法不需要參數。

C#多線程之Thread

using System;

C#多線程之Thread

using System.Threading;

C#多線程之Thread
C#多線程之Thread

public class Work

{

public static void Main()

{

        // To start a thread using a shared thread procedure, use

        // the class name and method name when you create the 

        // ParameterizedThreadStart delegate.

        //

        Thread newThread = new Thread(

        new ParameterizedThreadStart(Work.DoWork));

        // Use the overload of the Start method that has a

        // parameter of type Object. You can create an object that

        // contains several pieces of data, or you can pass any 

        // reference type or value type. The following code passes

        // the integer value 42.

        //

        newThread.Start(42);

        // To start a thread using an instance method for the thread 

        // procedure, use the instance variable and method name when 

        // you create the ParameterizedThreadStart delegate.

        //

        Work w = new Work();

        newThread = new Thread(

        new ParameterizedThreadStart(w.DoMoreWork));

        // Pass an object containing data for the thread.

        newThread.Start("The answer.");

    }

public static void DoWork(object data)

{

        Console.WriteLine("Static thread procedure. Data='{0}'",data);

    }

public void DoMoreWork(object data)

{

        Console.WriteLine("Instance thread procedure. Data='{0}'",data);

    }

}

2. 挂起線程

      挂起線程分為兩種,主動挂起和被動挂起。

      主動挂起可表示為:Thread.Sleep (Int32) 或 Thread.Sleep (TimeSpan) ,表示将目前調用線程挂起指定的時間。被動挂起表示為:Thread newThread = new Thread(new ThreadStart(Work.DoWork));

newThread.Start();

newThread.Join();

或者

Thread.CurrentThread.Join(50);

      Join表示在繼續執行标準的 COM 和 SendMessage 消息泵處理期間,阻止調用線程,直到某個線程終止為止。在[STAThread]訓示的Com線程模型中,我們應該使用Thread.CurrentThread.Join(50)這種方式。有一個與之有關的示例,

Thread.Sleep vs. Thread.CurrentThread.Join

3、終止線程

      在調用 Abort 方法以銷毀線程時,公共語言運作庫将引發 ThreadAbortException。ThreadAbortException 是一種可捕獲的特殊異常,但在 catch 塊的結尾處它将自動被再次引發。引發此異常時,運作庫将在結束線程前執行所有 finally 塊。由于線程可以在 finally 塊中執行未綁定計算,或調用 Thread.ResetAbort 來取消中止,是以不能保證線程将完全結束。如果您希望一直等到被中止的線程結束,可以調用 Thread.Join 方法。Join 是一個子產品化調用,它直到線程實際停止執行時才傳回。

      注意:在托管可執行檔案中的所有前台線程已經結束後,當公共語言運作庫 (CLR) 停止背景線程時,它不使用 System.Threading.Thread.Abort。是以,無法使用 ThreadAbortException 來檢測 CLR 何時終止背景線程。

      下面的示例說明如何中止線程。接收 ThreadAbortException 的線程使用 ResetAbort 方法取消中止請求并繼續執行。

C#多線程之Thread

using System;

C#多線程之Thread

using System.Threading;

C#多線程之Thread

using System.Security.Permissions;

C#多線程之Thread

public class ThreadWork 

{

public static void DoWork() 

  {

      try

      {

            for(int i=0; i<100; i++) 

            {

                Console.WriteLine("Thread - working."); 

                Thread.Sleep(100);

            }

        }

       catch(ThreadAbortException e) 

       {

            Console.WriteLine("Thread - caught ThreadAbortException - resetting.");

            Console.WriteLine("Exception message: {0}", e.Message);

            Thread.ResetAbort();

        }

        Console.WriteLine("Thread - still alive and working."); 

        Thread.Sleep(1000);

        Console.WriteLine("Thread - finished working.");

    }

}

C#多線程之Thread

        class ThreadAbortTest 

       {

              public static void Main() 

             {

                   ThreadStart myThreadDelegate = new ThreadStart(ThreadWork.DoWork);

                   Thread myThread = new Thread(myThreadDelegate);

                   myThread.Start();

                   Thread.Sleep(100);

                   Console.WriteLine("Main - aborting my thread.");

                   myThread.Abort();

                   myThread.Join();

                   Console.WriteLine("Main ending."); 

             }

       }

這段代碼産生以下輸出:

Thread - working.

Main - aborting my thread.

Thread - caught ThreadAbortException - resetting.

Exception message: Thread was being aborted.

Thread - still alive and working.

Thread - finished working.

Main ending.

      最後還有一點需要說明的是,在.NET Framework 2.0後,Thread對象的Suspend和Resume方法已被擯棄。原因在于使用 Suspend 和 Resume 方法來同步線程的活動。您無法知道挂起線程時它正在執行什麼代碼。如果您在安全權限評估期間挂起持有鎖的線程,則 AppDomain 中的其他線程可能被阻止。如果您線上程正在執行類構造函數時挂起它,則 AppDomain 中試圖使用該類的其他線程将被阻止。很容易發生死鎖。

繼續閱讀