C# 線程知識--Thread


1.線程基礎知識

    進程是應用程序運行時的一個實例,它包含:一個內核對象,Windows 操作系統用他來管理進程;一個地址空間,包含所有程序集可執行代碼和數據以及對線程堆棧和堆的內存分配。進程擁有自己的屬性以及調度優先級,當系統創建一個進程時,會自動創建一個主線程來執行進程地址空間里面的代碼,主線程可以創建多個子線程。進程地址空間中的代碼沒有任何線程執行時,系統就會終止進程和釋放地址空間。每個進程至少有一個或多個線程,每個線程都有自己的一個執行上下文環境即一組 CPU 寄存器和堆棧,多個運行線程都在進程的地址空間中同時執行代碼,系統會采用輪詢的方式為每個線程分配CPU時間片,線程之間就會進行上下文切換。
    線程是應用程序執行的最小單元,線程由一個唯一的線程ID進行標識。每個線程都包含:線程內核對象、線程環境塊、用戶模式棧、內核模式棧以及DLL 線程連接和線程分離通知等要素,線程都有內存空間和運行時間上的開銷。每個線程都會分配0~31的調到優先級,Windows 把線程划分7個相對優先級:Idle、Lowest、BelowNormal、Normal、AboveNormal、Highest和Time-Critical。CLR 保留了Idle和 Time-Critical ,在應用程序中只需要關注其他的5個優先級。CLR 把每個線程看着為前台線程或后台線程,進程中所有的前台線程停止運行時,運行的所有后台線程都會被CLR終止。
     多線程能夠提升應用程序的性能,改善用戶體驗,執行並發任務等,比如:執行復雜業務邏輯或長時間的計算任務、I/O操作、網絡請求時,使用后台線程處理這些受限制的任務,就不會阻塞主線。

2.使用 System.Threading.Thread 類創建線程

       在 C# 中可以使用 System.Threading.Thread 類來創建一個線程,該類有4個重要構造函數,每個構造函數都接受一個線程啟動時需要執行的函數(委托)以及線程的最大堆棧大小。

public Thread(ParameterizedThreadStart start);
public Thread(ThreadStart start);
public Thread(ParameterizedThreadStart start, int maxStackSize);
public Thread(ThreadStart start, int maxStackSize);

參數委托定義:

public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);

ParameterizedThreadStart 委托允許線程啟動時為執行方法傳遞一個需要使用的數據對象。
使用 Thread 類創建一個線程並執行任務,創建一個線程可以為線程制定線程的名稱、優先級、是否為后台線程以及設置線程的區域性等屬性。
   1:   private static void CreateThread()
   2:          {
   3:              //創建一個線程,可以構造 System.Threading.ParameterizedThreadStart 委托或 System.Threading.ThreadStart 委托實例
   4:              Thread thread = new Thread(state =>
   5:              {
   6:                  //線程啟動時需要執行的任務
   7:                  int sum = 0;
   8:                  //將當前線程掛起指定的時間,這兒是2000毫秒
   9:                  Thread.Sleep(2000);
  10:                  for (int i = 0; i < 1000; i++)
  11:                  {
  12:                      sum++;
  13:                  }
  14:                  Console.WriteLine("計數值:{0}", sum.ToString());
  15:              });
  16:              thread.Name = "執行長時間的計算處理";//設置線程的名稱
  17:              thread.Priority = ThreadPriority.AboveNormal;//設置線程優先級
  18:              thread.CurrentCulture = new System.Globalization.CultureInfo("EN");//設置線程區域性
  19:              Thread thread2 = new Thread(() => {
  20:                  Thread.Sleep(2000);
  21:                  Console.WriteLine("執行復雜任務");
  22:              });
  23:              //啟動線程,可以傳遞一個線程執行方法所使用的數據對象
  24:              thread.Start(null);
  25:              thread2.Start();
  26:          }

  3.Thread 類的一些重要的方法和屬性

     Thread.Sleep 靜態方法將當前線程掛起指定的時間,可以接受一個Int類型的表示掛起線程的毫秒數或TimeSpan類型的時間值。

   1:   static void Main(string[] args)
   2:          {
   3:              Thread t = new Thread(new ThreadStart(() => {
   4:                  Console.WriteLine("當前線程將會被阻塞1秒鍾。");
   5:                  Thread.Sleep(1000);
   6:                  Console.WriteLine("當前線程被阻塞1秒以后繼續執行。");
   7:              }));
   8:              t.Start();
   9:              Console.WriteLine("主線程執行任務。");
  10:          }

子線程會被阻塞1秒鍾。

執行結果:image

    Join 方法會阻塞調用線程,直到某個線程終止或經過了指定時間為止。

   1:   static void Main(string[] args)
   2:          {
   3:              Console.WriteLine("主線程開始執行任務。");
   4:              Thread t = new Thread(new ThreadStart(() => {
   5:                  Console.WriteLine("子線程執行任務,並阻塞調用線程。");
   6:                
   7:              }));
   8:              t.Start();
   9:              //調用線程被阻塞2000毫秒
  10:              t.Join(2000);
  11:              Console.WriteLine("主線程被阻塞后繼續執行任務。");
  12:          }
  程序執行結果:image

    Interrupt  方法中斷處於 WaitSleepJoin 線程狀態的線程,可以通過線程的 ThreadState 屬性獲得當前線程的狀態,每個線程都具有如下的狀態:

   1:  public enum ThreadState
   2:      {
   3:          Running = 0,
   4:          StopRequested = 1, 
   5:          SuspendRequested = 2,
   6:          Background = 4,
   7:          Unstarted = 8,
   8:          Stopped = 16,
   9:          WaitSleepJoin = 32,
  10:          Suspended = 64,
  11:          AbortRequested = 128,
  12:          Aborted = 256,
  13:      }

程序示例:

1: static void Main(string[] args)

   2:          {
   3:              Console.WriteLine("主線程開始執行任務。");
   4:              Thread t = null;
   5:                t=  new Thread(new ThreadStart(() => {
   6:                  Thread.Sleep(2000);
   7:                  Console.WriteLine("子線程執行任務。");
   8:              }));
   9:              Console.WriteLine("調用Start方法前子線程的狀態:{0}",t.ThreadState.ToString());
  10:              t.Start();
  11:              Console.WriteLine("調用Start方法后子線程當前狀態:{0}", t.ThreadState.ToString());
  12:              //調用線程被阻塞2000毫秒
  13:              t.Join(2000);
  14:              Console.WriteLine("調用Join方法后子線程的狀態:{0}", t.ThreadState.ToString());
  15:              Thread.Sleep(1000);
  16:              //終止處於 WaitSleepJoin 狀態的的線程。
  17:              t.Interrupt();
  18:              Console.WriteLine("調用Interrupt方法后子線程的狀態:{0}", t.ThreadState.ToString());
  19:              Console.WriteLine("主線程被阻塞后繼續執行任務。");
  20:          }

執行結果image

      Abort 方法在調用此方法的線程上引發 System.Threading.ThreadAbortException 異常,以開始終止此線程的過程。

   1:   static void Main(string[] args)
   2:          {
   3:              Thread t = null;
   4:              t = new Thread(() =>
   5:                  {
   6:                      try
   7:                      {
   8:                          Thread.Sleep(1000);
   9:                          Console.WriteLine("子線程執行任務。");
  10:                      }
  11:                      catch
  12:                      {
  13:                          Console.WriteLine("子線程引發終止異常,線程狀態:{0}。", Thread.CurrentThread.ThreadState.ToString());
  14:                      }
  15:                      finally
  16:                      {
  17:                          Console.WriteLine("進入finally塊語句子線程狀態:{0}。", Thread.CurrentThread.ThreadState.ToString());
  18:                      }
  19:                  });
  20:              t.Start();
  21:              Thread.Sleep(1000);
  22:              //終止子線程
  23:              t.Abort();
  24:              t.Join();
  25:              Console.WriteLine("子線程線程狀態:{0}。", t.ThreadState.ToString());
  26:          }

執行結果:image

     Suspend 方法掛起線程和Resume 繼續已掛起的線程,這兩個方法已經過時。

    線程的重要屬性:

     Thread.CurrentContext 靜態屬性獲取線程正在其中執行的當前上下文。

     Thread.CurrentThread 靜態屬性獲取當前正在運行的線程。

     Name 獲取或設置線程的名稱。

     IsAlive 獲取當期線程的執行狀態。

     IsBackground 獲取或設置線程是否為后台線程。

     IsThreadPoolThread 指示一個線程是否屬於托管線程池線程。

     ManagedThreadId 獲取當前線程的唯一標識符。

     Priority 獲取或設置線程的調度優先級。

     ThreadState 獲取當前線程的狀態。

關於線程的具體詳情參見MSDN對 System.Threading.Thread 類的描述。

本文只是簡單的介紹了線程的基礎知識以及使用和一些方法屬性,需要在具體業務中實踐,合理使用線程這種寶貴的資源以提升應用程序性能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM