Task,async,await之间的关系

纠结了很久的Task,async,await这3货的关系,今天终于慢慢解开了面纱。

1、对于一个 async 标记的方法并不是再执行的时候就立即 开了一个新的线程,这点很重要,可以通过打印出当亲线程id来证明,而是当在 async 方法里遇到 await 的时候才会真正的开启一个线程。

2、当开启了一个线程后,此时就会有主线程和新线程2个线程,同时执行,并不会因为起了新线程后就继续执行新线程而继续让主线程尴尬的等着,这点也很重要(如果一个async方法里有多个await ,那就按顺序执行)。

3、最重要的一点,如果你的 async方法 有返回值 Task<T> ,而当你 一定要 取到这个返回值的时候,就尴尬了,此时一定是同步的,就是一定要把 新线程执行完才肯罢休。

好了,下面开始验证

 

  static void Main(string[] args)
        {
            
            GetInfo();
            Write();

            Console.ReadKey();
        }    


 static async void GetInfo()
        {
            await Task.Run(() =>
            {
                Console.WriteLine("开始休息");
                Thread.Sleep(3000);
                Console.WriteLine("结束休息");
            });


            await Task.Run(() =>
            {
                Console.WriteLine("3333休息");
                Thread.Sleep(3000);
                Console.WriteLine("3333休息");
            });

        }

        static  void Write()
        {
            Console.WriteLine("浪里个浪");
            
        }

 

 

接下来验证带返回值的。

 

 static async Task<string> Info()
        {
            Console.WriteLine("又要休息");
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

            var res = await Task.Run(() =>
            {
                for (int i = 0; i < 1000000000; i++)
                {

                }; Console.WriteLine(Thread.CurrentThread.ManagedThreadId); Console.WriteLine("休息好看了"); return "success";
            });
            
            Console.WriteLine(res+"111111111111111111111");
            
            return res;
        }

        static  void Write1()
        {
            Console.WriteLine("浪里个浪");
           
        }

 

第一种情况:

 

当调用 Info()时候,此时还在主线程了,自然同步执行,然后遇到了await,然后新起了线程10,然后就继续回到主线程,打印出  “修改下哈看了11111”,因为先调用了 Task.Result,所以此主线程阻塞,执行完新线程,直到打印返回结果,然后继续执行主线程。

 

第二种情况:

 

 当调用 Info()时候,此时还在主线程了,自然同步执行,然后遇到了await,然后新起了线程10,然后就继续回到主线程,打印出  “修改下哈看了11111”,然后新线程比较耗时,所以主线程先打印出了 Write1() 方法,然后调用了 Task.Result,所以此主线程阻塞,执行完新线程,打印返回结果,然后继续执行主线程,打印出了“休息好看了1122122”。

 

问题解决,源代码如下:

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            Task<string> res = Info();
            Console.WriteLine("休息好看了11111");
            Write1();
            Console.WriteLine(res.Result);
            Console.WriteLine("休息好看了1122122");
           
   

            //GetInfo();
            //Write();

            Console.ReadKey();
        }
        static void Write(int i)
        {
            Console.WriteLine(i);
        }

        static async void GetInfo()
        {
            await Task.Run(() =>
            {
                Console.WriteLine("开始休息");
                Thread.Sleep(3000);
                Console.WriteLine("结束休息");
            });


            await Task.Run(() =>
            {
                Console.WriteLine("3333休息");
                Thread.Sleep(3000);
                Console.WriteLine("3333休息3333");
            });

        }

        static  void Write()
        {
            Console.WriteLine("浪里个浪");
            
        }

        static async Task<string> Info()
        {
            Console.WriteLine("又要休息");
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

            var res = await Task.Run(() =>
            {
                for (int i = 0; i < 1000000000; i++)
                {

                }; Console.WriteLine(Thread.CurrentThread.ManagedThreadId); Console.WriteLine("休息好看了"); return "success";
            });
            
            Console.WriteLine(res+"111111111111111111111");
            
            return res;
        }

        static  void Write1()
        {
            Console.WriteLine("浪里个浪");
           
        }
    }

 补充:https://mp.weixin.qq.com/s/BAqwvHfwRMrugBFKc8hF4w

posted on 2018-02-06 18:19  奔游浪子  阅读(816)  评论(0)    收藏  举报

导航