开发者

C#中async和await的深入分析

开发者 https://www.devze.com 2022-12-02 12:09 出处:网络 作者: code
目录大概理解深入分析await和Wait()的区别去掉Task.Run的Wait小结其他.Await();总结大概理解
目录
  • 大概理解
  • 深入分析
    • await和Wait()的区别
    • 去掉Task.Run的Wait
    • 小结
  • 其他
    • .Await();
  • 总结

    大概理解

    查了一个小时的资料:async和await

    发现这个大神的解释一针见血,深得我心!以最简单的例子,解释了async和await。妙~~~

    大多情况下,分开才能体现async和await的价值!

    C#中async和await的深入分析

     但,await 并没有这么简单。

    深入分析

    await和Wait()的区别

    接下来继续往下看:

    await Task.Delay(3000);  和Task.Delay(3000).Wait();   有没有区别?

    上代码:

    using System.Diagnostics;
     
    namespace await_async2
    {
        internal class Program
        {
     
            static  public void TestWait()
            {
                var t = Task.Factory.StartNew(() =>
                {
                    Console.WriteLine("Start");
                    Task.Delay(3000).Wait();
                    Console.WriteLine("Done");
                });
                t.Wait();
                Console.WriteLine("All done");
            }
     
     
            static public void TestWait2()
            {
                var t = Task.Factory.StartNew(async () =>
                {
                    Console.WriteLine("Start");
                    await Task.Delay(3000);
                    Cwww.devze.comonsole.WriteLine("Done");
                });
                t.Wait();
                Console.WriteLine("All done");
            }
     
            static pubwww.devze.comlic void TestWait3()
            {
                var t = Task.Run(async () =>
                {
                    Console.WriteLine("Start");
                    await Task.Delay(3000);
                    Console.WriteLine("Done");
                });
                t.Wait();
                Console.WriteLine("All done");
            }
     
            static void Main(string[] args)
            {
                TestWait2();
                //避免程序提前退出,导致一些现象看不到
                Task.Delay(5000).Wait();
            }
        }
    }

    首先,强调一下,最后一句 Task.Delay(5000).Wait(); 是必须的,不然,程序提前退出,导致一些现http://www.devze.com象看不到,从而蒙蔽了我们。

    第1段代码TestWait执行效果,如下:

    C#中async和await的深入分析

    第2段代码TestWait2执行效果,如下:

    C#中async和await的深入分析

    第3段代码TestWait3执行效果,如下:

    C#中async和await的深入分析

    现在给出结论:

    Task.Delay(3000).Wait(); 这个就是同步等。

    a编程客栈wait Task.Delay(3000); 因为没有分开来写(见第一张图),所以基本和同步等没有区别。

    但是如果 await Task.Delay(3000); 是写到:Task.Factory.StartNew里面的

    static public void TestWait2()
            {
                var t = Task.Factory.StartNew(async () =>
                {
                  js  Console.WriteLine("Start");
                    await Task.Delay(3000);
                    Console.WriteLine("Done");
                });
                t.Wait();
                Console.WriteLine("All done");
            }

    那这个效果不一样了,他们执行的权限丢出去了有点像python里的yeild,来看下程序的执行顺序:

    C#中async和await的深入分析

     这里就看出了:await Task.Delay(3000);  和Task.Delay(3000).Wait(); 的区别了。(但是这种情况如果在道Task.Run里面就体现不出来!)

    然后,我有简单做了一个实验:

    C#中async和await的深入分析

    这就更明了了, await Task.Delay(3000); 就像设置了一个回调,一旦三秒时间一到,程序的指针就会回到await Task.Delay(3000);后面的位置,直到函数执行结束。再回到之前的位置。这就是所谓的用同步的方式写异步的代码吧

    但是,为啥在Task.Factory.StartNew才会体现出来,这个我就不清楚了,请各位大佬指点一下。

    去掉Task.Run的Wait

    再来对比一下,下面这两个函数:

     static public void TestWait8()
     {
         var t = Task.Run(async () =>
         {
             Console.WriteLine("Start");
             await Task.Delay(3000);
             Console.WriteLine("Done");
         });
         Console.WriteLine("All done");
     }
     static public void TestWait8_5()
     {
         var t = Task.Factory.StartNew(async () =>
         {
             Console.WriteLine("Start");
             await Task.Delay(3000);
             Console.WriteLine("Done");
         });
         t.Wait();
         Console.WriteLine("All done");
     }

    先看第一个TestWait8,由于Task.Run不再调用 t.Wait(),Task.Run内部这个线程主线程是并行的关系。程序指针会在两个线程中来回切换。如果一方中写了awa开发者_Go教程it xxx,那程序指针必然跳到另一个线程。直达await结束才可能返回。 这种情形是比较多的。此时await能节省大量等待时间(比如IO操作时间),充分利用等待时间。

    此时 Console.WriteLine("All done");会最先被打印出来。

    再看第二个TestWait8_5(其实就是回顾一下),当程序执行到t.Wait()时,程序不会继续向下了,(此时因为有t.Wait()的存在,所以子线程其实是优先于主线程的)而是进入到子线程的内部进程,试图将这个线程执行完,但是再线程里面遇到又遇到await Task.Delay(3000);此时程序指针不会再这里死等,程序指针又跳回主线程继续执行,直到三秒到了之后就会回到子线程,子线程执行完了之后,再回到主线程。

    但是如果吧TestWait8_5 中    Task.Factory.StartNew 换成 Task.Run ,那么前面的过程一样,只是执行到await Task.Delay(3000);时候,此时会死等,不会跳到主线程,而是一定等到这个子线程完结,再回主线程。

    小结

    总结一下就是,遇到await 一定会等,至于程序指针是先跳到其他线程,还是在此线程死等,就看你的线程函数这么写的了。

    其他

    .Await();

    最后,还有个:Task.Delay(3000).Await();

    这个是prsim对Task写的的一个拓展方法(避免在主线程调用时,阻塞UI):

    C#中async和await的深入分析

    总结

    到此这篇关于C#中async和await的文章就介绍到这了,更多相关C# async和await内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号