Luồng và Nhiệm vụ Trong .NET

Luồng chính chạy đồng bộ sẽ in ra ba dòng theo thứ tự

  internal class ChuongTrinh
  {
      static void GiaiDoanChinh(string[] thamSo)
      {
          Console.WriteLine($"1 Luồng chính bắt đầu");

          Console.WriteLine($"2 Luồng chính đang làm việc");
        
          Console.WriteLine($"3 Luồng chính kết thúc");
      }
  }

In ra 1-2-3 liên tiếp chứng tỏ quá trình là đồng bộ

Luồng con sinh ra từ luồng chính mặc định là luồng tiền cảnh không làm chậm luồng chính

 internal class ChuongTrinh
 {
     static void GiaiDoanChinh(string[] thamSo)
     {
         Console.WriteLine($"1 Luồng chính bắt đầu");

         Thread luongCon = new Thread(() => {
             Console.WriteLine($"2 Luồng con đang làm việc");
         });
         luongCon.Start();
         Console.WriteLine($"3 Luồng chính kết thúc");
     }
 }

Có thể thấy luồng con không làm chậm luồng chính

Để in ra theo thứ tự thì phải sử dụng Join hoặc Sleep. Dưới đây là ví dụ với Join

 static void GiaiDoanChinh(string[] thamSo)
 {
     Console.WriteLine($"1 Luồng chính bắt đầu");

     Thread luongCon = new Thread(() => {
         Console.WriteLine($"2 Luồng con đang làm việc");
     });
     luongCon.Start();
     <strong>luongCon.Join();</strong>
     Console.WriteLine($"3 Luồng chính kết thúc");
 }

Join buộc luồng chính đợi luồng con hoàn thành trước khi tiếp tục

Ví dụ với Sleep 1 giây để làm chậm luồng chính

 internal class ChuongTrinh
 {
     static void GiaiDoanChinh(string[] thamSo)
     {
         Console.WriteLine($"1 Luồng chính bắt đầu");

         Thread luongCon = new Thread(() => {
             Console.WriteLine($"2 Luồng con đang làm việc");
         });
         luongCon.Start();
         //luongCon.Join();
         <strong>Thread.Sleep(1000);</strong>
         Console.WriteLine($"3 Luồng chính kết thúc");
     }
 }

Nếu Sleep nằm trong luồng con

 internal class ChuongTrinh
 {
     static void GiaiDoanChinh(string[] thamSo)
     {
         Console.WriteLine($"1 Luồng chính bắt đầu");

         Thread luongCon = new Thread(() => {
            <strong> Thread.Sleep(1000);</strong>
             Console.WriteLine($"2 Luồng con đang làm việc");
         });
         luongCon.Start();
         //Thread.Sleep(1000);
         Console.WriteLine($"3 Luồng chính kết thúc");
     }
 }

Kết quả không theo thứ tự. Kết luận Sleep làm chậm luồng hiện tại

Với Task trong luồng chính

Task lấy luồng từ pool luồng. Nếu có luồng rảnh sẽ sử dụng, nếu không có sẽ tạo mới

  internal class ChuongTrinh
  {
      static async Task GiaiDoanChinh(string[] thamSo)
      {
          Console.WriteLine($"1 Luồng chính bắt đầu");
          await Task.Run(() =>
             {
                 Console.WriteLine($"2 Task đang làm việc");
             });

          Console.WriteLine($"3 Luồng chính kết thúc");
        
      }
  }

await buộc luồng chính chờ Task hoàn thành

Thử nghiệm await trong luồng con

   static async Task GiaiDoanChinh(string[] thamSo)
   {
       Console.WriteLine($"1 Luồng chính bắt đầu");

       Thread luongCon = new Thread(async () =>
       {
           await Task.Run(() =>
           {
               Console.WriteLine($"2 Task đang làm việc");
           });
           await Task.Run(() =>
           {
               Console.WriteLine($"2.1 Task đang làm việc");
           });
           await Task.Run(() =>
           {
               Console.WriteLine($"2.2 Task đang làm việc");
           });
       });
       luongCon.Start(); 
       Console.WriteLine($"3 Luồng chính kết thúc");

   }

Chỉ in được đến "2 Task đang làm việc" vì luồng chính kết thúc trước khi các Task còn lại chạy xong

Chuyển Task thành luồng tiền cảnh để đảm bảo in đầy đủ

 internal class ChuongTrinh
 {
     static void GiaiDoanChinh(string[] thamSo)
     {
         Console.WriteLine($"1 Luồng chính bắt đầu");
       
         Thread luongCon = new Thread(async () =>
         {
             await Task.Run(() =>
             {
                <strong> Thread.CurrentThread.IsBackground = false;</strong>
                 Console.WriteLine($"2 Task đang làm việc, đây là luồng tiền cảnh {Thread.CurrentThread.IsBackground} ");
             });
             await Task.Run(() =>
             {
                <strong> Thread.CurrentThread.IsBackground = false;</strong>
                 Console.WriteLine($"2.1 Task đang làm việc, đây là luồng tiền cảnh {Thread.CurrentThread.IsBackground} ");
             });
             await Task.Run(() =>
             {
                <strong> Thread.CurrentThread.IsBackground = false;        </strong>          
                 Console.WriteLine($"2.2 Task đang làm việc, đây là luồng tiền cảnh {Thread.CurrentThread.IsBackground} ");
             });
         });
      
         luongCon.Start();
        <strong> Thread.Sleep(1000);</strong>
         Console.WriteLine($"3 Luồng chính kết thúc");
     }
 }

Thiết lập Thread.CurrentThread.IsBackground = false; để Task chạy như luồng tiền cảnh. Thread.Sleep(1000); giữ luồng chính chờ 1 giây để Task có thời gian thực thi hoàn toàn

Thẻ: .NET threading Async

Đăng vào ngày 12 tháng 6 lúc 01:41