天天看點

C# 多線程學習筆記 - 1

本文主要針對 GKarch 相關文章留作筆記,僅在原文基礎上記錄了自己的了解與摘抄部分片段。

遵循原作者的 CC 3.0 協定。

如果想要了解更加詳細的文章資訊内容,請通路下列位址進行學習。

原文章位址:https://blog.gkarch.com/threading/part1.html

基礎知識

  1. 靜态字段是在所有線程當中共享狀态的。
  2. 一個線程被阻塞時,不會消耗 CPU 資源。
  3. Join 可以等待另一個線程結束,Sleep 可以将線程阻塞指定的時間,兩者使用時線程都是阻塞狀态。
  4. Join 可以設定逾時時間,當線程執行超過指定時間傳回 False。
  5. Thread.Sleep(0)

    會釋放目前時間片,将 CPU 資源讓出給其他線程。
  6. Thread.Sleep(0)

    作用與

    Thread.Yield()

    作用一樣,後者隻會讓出給目前核心的其他線程。
  7. Thread.Yield()

    執行時會影響到程式的話,基本可以确定代碼存在 Bug。
  8. 在使用 Lambda 表達式啟動線程并傳入變量的時候,不要在啟動線程之後更改被捕獲變量的值。
  9. 線程分為前台線程與背景線程,當所有前台線程中止時,程式自動退出。
  10. 可以顯式地提高線程優先級,但可能會導緻線程饑餓。

線程池

  1. 由于線程建立成本高昂(私有局部變量棧,每個線程預設占用 1 MB記憶體),是以一般都會使用線程池來進行線程的建立與回收。
  2. 線程池線程可以臨時更改其優先級,在回收後會恢複預設狀态。
  3. 開發人員可以通過

    Thread.CurrentThread.IsThreadPoolThread

    屬性查詢線程是否運作線上程池中。
  4. 通過查詢 Task.Result 會導緻目前線程阻塞,直到任務執行完成,如果發生錯誤,則會将異常包裝到

    AggregateException

    異常内進行抛出。
  5. 通過異步委托可以快速建立一個工作線程。
    1. 建立目标方法委托。
    2. 在委托上調用

      BeginInvoke()

      方法,儲存其

      IActionResult

      傳回值。
    3. 需要傳回結果時,調用

      EndInvoke()

      方法,傳遞儲存的

      IActionResult

      對象。
    class Program
    {
    	static void Main(string[] args)
    	{
    		Func<string, int> work = Work;
    
    		var result = work.("測試",null,null);
    
    		Console.WriteLine("獲得結果");
    		
    		work.EndInvoke(result);
    	}
    
    	public static int Work(string inputStr)
    	{
    		Console.Write(Thread.CurrentThread);
    		return inputStr.Length;
    	}
    }
               

    注意:

      上述代碼在 .NET Core 平台上是無法運作的。

  6. 異步委托在調用

    BeginInvoke()

    的時候可以傳入回調方法。
  7. 線程池可以通過

    ThreadPool.SetMaxThreads

    ThreadPool.SetMinThreads

    進行優化。