.net Thread Task

正常 主线程 顺序打印 下面 三行内容

  internal class Program
  {
      static  void Main(string[] args)
      {

          Console.WriteLine($"1主线程启动");

          Console.WriteLine($"2主线程在作业");
        
          Console.WriteLine($"3主线程结束");
      }
  }

 

顺序打印 123 说明 是同步的

 

 

Thread 是主线程 上的子线程  默认是前台线程 不会阻塞主线程

 internal class Program
 {
     static  void Main(string[] args)
     {

         Console.WriteLine($"1主线程启动");

         //Console.WriteLine($"2主线程在作业");
         Thread thread = new Thread(() => {
             Console.WriteLine($"2Thread程在作业");
         });
         thread.Start();
         Console.WriteLine($"3主线程结束");
     }
 }

 

可以看到 Thread 子线程 没有阻塞 主线程打印

那么如何 顺序打印呢, 也就是阻塞主线程 呢 答案用 join 或者 sleep

下面是join 

 static  void Main(string[] args)
 {

     Console.WriteLine($"1主线程启动");

     //Console.WriteLine($"2主线程在作业");
     Thread thread = new Thread(() => {
         Console.WriteLine($"2Thread程在作业");
     });
     thread.Start();
     thread.Join();
     Console.WriteLine($"3主线程结束");
 }

  

join  主线程等待子线程 作业结束 才进行后续的打印

 下面 是sleep 1秒 使主线程 阻塞了 1秒

 internal class Program
 {
     static  void Main(string[] args)
     {

         Console.WriteLine($"1主线程启动");

         //Console.WriteLine($"2主线程在作业");
         Thread thread = new Thread(() => {
             Console.WriteLine($"2Thread程在作业");
         });
         thread.Start();
         //thread.Join();
         Thread.Sleep(1000);
         Console.WriteLine($"3主线程结束");
     }
 }

  

 

如果 sleep 在 thread 中 会发现什么情况

 internal class Program
 {
     static  void Main(string[] args)
     {

         Console.WriteLine($"1主线程启动");

         //Console.WriteLine($"2主线程在作业");
         Thread thread = new Thread(() => {
             Thread.Sleep(1000);
             Console.WriteLine($"2Thread程在作业");
         });
         thread.Start();
         //thread.Join();
         //Thread.Sleep(1000);
         Console.WriteLine($"3主线程结束");
     }
 }

 结果 是 没有顺序 打印 结论是 sleep 是让 当前线程 阻塞,也就是 sleep 在主线程 调用 就阻塞主线程 在子线程中调用就阻塞子线程

 

下面 是Task 在主线程情况 

Task 是后台线程 从线程池中取得线程,如果线程池中有空闲线程就获取如果没有就新建一个线程,如果线程池中满了,后续线程需要等待才能继续操作

  internal class Program
  {
      static async Task Main(string[] args)
      {

          Console.WriteLine($"1主线程启动");
          await Task.Run(() =>
             {
                 Console.WriteLine($"2Task在作业");
             });

          Console.WriteLine($"3主线程结束");
        
      }
  }

  

await 等待 后台线程 作业结束 才能继续打印内容 因为是在主线程中执行的 所以 阻塞了主线程, 也就是说await 阻塞了当前线程,await在主线程是使用就阻塞主线程

,在子线程中使用就阻塞子线程

 

下面验证  也就是说await 阻塞了当前线程,await在主线程是使用就阻塞主线程,在子线程中使用就阻塞子线程

   static async Task Main(string[] args)
   {

       Console.WriteLine($"1主线程启动");

       Thread thread = new Thread(async () =>
       {
           await Task.Run(() =>
           {
               Console.WriteLine($"2Task在作业");
           });
           await Task.Run(() =>
           {
               Console.WriteLine($"2.1 Task在作业");
           });
           await Task.Run(() =>
           {
               Console.WriteLine($"2.2 Task在作业");
           });
       });
       thread.Start(); 
       Console.WriteLine($"3主线程结束");

   }

 下面 情况 是只 打印了  2Task在作业 ,2.1 Task在作业 ,2.2 Task在作业 这俩为什么没有打印出来呢,原因是 task 是后台工作线程 ,Thread 和主线程 都是前台线程,前台线程关闭 后台线程 直接结束,也就是说 2Task在作业 打印完 刚好前台线程结束了 所以后面的 内容没有打印

 那么我把 3个 Task 设置为前台线程 就能打印了 同时也能看间 3Task 顺序打印 就证明了 我的猜想

 

 internal class Program
 {
     static void Main(string[] args)
     {

         Console.WriteLine($"1主线程启动");
       
         Thread thread = new Thread(async () =>
         {
             await Task.Run(() =>
             {
                 Thread.CurrentThread.IsBackground = false;
                 Console.WriteLine($"2Task在作业,是否是后台线程{Thread.CurrentThread.IsBackground} ");
             });
             await Task.Run(() =>
             {
                 Thread.CurrentThread.IsBackground = false;
                 Console.WriteLine($"2.1 Task在作业,是否是后台线程{Thread.CurrentThread.IsBackground} ");
             });
             await Task.Run(() =>
             {
                 Thread.CurrentThread.IsBackground = false;                  
                 Console.WriteLine($"2.2 Task在作业,是否是后台线程{Thread.CurrentThread.IsBackground} ");
             });
         });
      
         thread.Start();
         Thread.Sleep(1000);
         Console.WriteLine($"3主线程结束");
     }
 }


上面 代码 Thread.CurrentThread.IsBackground = false; 设置为前台线程 由于 设置前台线程还需要些时间 所以 在 thread.Start(); 后面

Thread.Sleep(1000); 阻塞了主线程 又因为 Task 是异步的 所以 即使阻塞了主线 异步的Task 是可以执行的 这样就给 Task 设置为前台线程争取了1秒时间 所以才能
看到下面的结果 Task 是顺序的 打印

 

 

 

posted on 2024-07-08 10:13  是水饺不是水饺  阅读(8)  评论(0)    收藏  举报

导航