<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      C#多線程編程(二)線程池與TPL

      一、直接使用線程的問題

      1. 每次都要創(chuàng)建Thread對象,并向操作系統(tǒng)申請創(chuàng)建一個線程,這是需要耗費CPU時間和內存資源的。
      2. 無法直接獲取線程函數返回值
      3. 無法直接捕捉線程函數內發(fā)生的異常

            使用線程池可以解決第一個問題

      二、.NET中的線程池

            在這里只簡單的介紹一下ThreadPool,由于TPL的存在,我工作中大部分使用的是TPL中的類,這是后面介紹的重點。

      1. ThreadPool.QueueUserWorkItem

            這個方法有三個重載

      • public static bool QueueUserWorkItem(WaitCallback callBack)
      • public static bool QueueUserWorkItem(WaitCallback callBack, object? state)
      • public static bool QueueUserWorkItem<TState>(Action<TState> callBack, TState state, bool preferLocal)

            第一個函數需要傳入一個WaitCallback 委托,該委托的定義如下

      • public delegate void WaitCallback(object? state);

            第二個函數多了一個state參數,表示需要傳給委托的參數,若無需傳參調用第一個函數即可。

            第三個函數是一個泛型版本,還多了一個布爾類型的參數preferLocal,這個參數表示傳入的委托將會在放入線程池工作線程的本地隊列還是線程池的全局隊列。

            線程池內部有本地隊列全局隊列的概念,線程池遵循生產者-消費者模式,線程池還可以為線程數量提供良好的伸縮性,有關.NET線程池的詳細信息,請參見https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.threadpool?view=netcore-3.1

            需要注意的是,線程池中的線程默認為后臺線程,這意味著如下代碼一般不能按預期工作。

      1 static void Main(string[] args)
      2 {
      3      ThreadPool.QueueUserWorkItem(state =>
      4      {
      5          Thread.Sleep(100);
      6          Console.WriteLine("執(zhí)行完畢");
      7      });
      8 }


            并且由于線程會被復用,所以不能作依賴于某個特定線程的操作。

      2. 何時不使用線程池(摘錄微軟文檔)

      1. 需要一個前臺線程。
      2. 需要具有特定優(yōu)先級的線程。
      3. 擁有會導致線程長時間阻塞的任務。 線程池具有最大線程數,因此大量被阻塞的線程池線程可能會阻止任務啟動。
      4. 需將線程放入單線程單元。 所有 ThreadPool 線程均位于多線程單元中。
      5. 需具有與線程關聯的穩(wěn)定標識,或需將一個線程專用于一項任務。

      三、更方便的解決方案(使用TPL)

      1.處理線程池未解決的問題

            線程池雖然解決了線程資源浪費的問題,但是以下兩點還未解決

      1. 無法直接獲取線程函數返回值
      2. 無法直接捕捉線程函數內發(fā)生的異常

            在上一篇中MyTask類可以解決這兩個問題,但由于內部是每個Task直接開一個線程,資源浪費的問題還是沒有解決,所以我們是不是能夠把兩者結合呢?

      2.Task初體驗

      無返回值無異常

       1 static void Main(string[] args)
       2 {
       3      Task task = new Task(() => 
       4      {
       5          Thread.Sleep(100);
       6          Console.WriteLine($"是否是線程池線程:{Thread.CurrentThread.IsThreadPoolThread}");
       7      });
       8      task.Start();
       9      try
      10      {
      11          task.Wait();
      12      }
      13      catch(Exception e)
      14      {
      15          Console.WriteLine(e.Message);
      16      }
      17 }



      輸出如下:

      image

      無返回值有異常

       1 static void Main(string[] args)
       2 {
       3      var task = new Task(() => 
       4      {
       5          Console.WriteLine($"是否是線程池線程:{Thread.CurrentThread.IsThreadPoolThread}");
       6          var task1 = new Task(() => 
       7          {
       8              Console.WriteLine($"是否是線程池線程:{Thread.CurrentThread.IsThreadPoolThread}");
       9              throw new Exception("延續(xù)任務發(fā)生異常");
      10          },TaskCreationOptions.AttachedToParent);
      11          task1.Start();
      12          throw new Exception("主任務發(fā)生異常");
      13      });
      14 
      15     task.Start();
      16      try
      17      {
      18          task.Wait();
      19      }
      20      catch(AggregateException ae)//Task內部包裝了異常,有異常發(fā)生Wait()內部會拋出一個聚合異常
      21      {
      22          foreach(var e in ae.Flatten().InnerExceptions)//把階梯式的聚合異常變?yōu)楸馄降漠惓?/span>
      23          {
      24              Console.WriteLine(e.Message);
      25          }
      26      }
      27 }


      image

            有返回值的就不演示了。可以看到,使用Task解決了開始的三種問題,但事物總是具有兩面性,有優(yōu)點也有缺點,Task會帶來額外的內存分配,Task抽象層次過高,深入理解并使用好并非易事,在與async/await關鍵字配合編寫異步代碼時更加突出。

            網上關于Task的使用例子很多,微軟文檔也很全,我在此這里補充一下需要注意的地方。

      • 任務是托管線程上更高層次的抽象
      • 任務的執(zhí)行由任務調度器(TaskScheduler)決定
      • 默認的任務調度器是線程池調度器,它使用線程池執(zhí)行任務
      • Task.Run()靜態(tài)方法和Task.Start()實例方法以及默認的任務工廠Task.Factory都是使用默認的線程池任務調度器
      • 因此說Task是對線程池的封裝是不準確的
      • 通過指定TaskCreationOptions.LongRunning枚舉便可讓任務在非線程池中的線程上執(zhí)行,這樣可以避免長期占用線程池中的線程,因為線程池是有大小的,一般線程池用來處理簡單但量多的工作。

      上一篇:(一)進程與線程

      posted @ 2020-07-07 10:43  白煙染黑墨  閱讀(1208)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产成人高清亚洲一区二区| 黑人巨大亚洲一区二区久| 无码人妻丰满熟妇片毛片| 国产乱码精品一区二区三| 永定县| 国产精品一区二区三区专区| 熟妇人妻无码中文字幕老熟妇| 99RE8这里有精品热视频| 青青草原国产精品啪啪视频| 国产重口老太和小伙| 日韩一区二区三区在线视频| 免费看的一级毛片| 亚洲一区二区三区在线播放无码| 国产女同一区二区在线| 日本高清一区免费中文视频| 红安县| 竹菊影视欧美日韩一区二区三区四区五区 | 国产精品久久久久7777| 亚洲AV日韩精品久久久久| 国产精品久久自在自线不卡| 免费视频一区二区三区亚洲激情 | 国产在线午夜不卡精品影院| 亚洲精品久久久久国产| 日韩精品一区二区蜜臀av| 日韩av日韩av在线| 激情五月天自拍偷拍视频| 丝袜美腿一区二区三区| 一 级做人爱全视频在线看| 啦啦啦视频在线日韩精品| 产综合无码一区| 97在线视频人妻无码| 亚洲色成人一区二区三区| 日本丰满熟妇hd| 18av千部影片| 国产黄色一区二区三区四区| 亚洲无人区码二码三码区| 精品亚洲精品日韩精品| 鲁丝片一区二区三区免费| 国产乱人伦真实精品视频| 欧美高清一区三区在线专区| 亚洲av永久无码天堂影院|