zoukankan      html  css  js  c++  java
  • C#中的async/await

    async方法只能有三种返回值:void, Task, Task<T>。

    async void只能直接调用,与调用方并行执行。

    async Task可以直接调用,也可以await调用,直接调用是并行执行,await调用会等待执行完。

    async Task<T>与async Task类似,只是通过await方式调用可以获得T类型的返回值。

    下面通过代码做了一些实验。

        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine(DateTime.Now.ToString() + " : " + "程序启动");
                Test8();
                Console.WriteLine(DateTime.Now.ToString() + " : " + "程序结束");
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine(DateTime.Now.ToString() + " : Ticks");
                    Thread.Sleep(1000);
                }
                Console.ReadLine();
            }
    
            private static void TaskFunc(int n)
            {
                Console.WriteLine(DateTime.Now.ToString() + " : " + "Begin Call TaskFunc(" + n + ")");
                Thread.Sleep(2000);
                Console.WriteLine(DateTime.Now.ToString() + " : " + "End Call TaskFunc(" + n + ")");
            }
    
            /***********************************************************
            2018/9/25 10:51:34 : 程序启动
            2018/9/25 10:51:34 : Begin Call TaskFunc(1)
            2018/9/25 10:51:36 : End Call TaskFunc(1)
            2018/9/25 10:51:36 : Begin Call TaskFunc(2)
            2018/9/25 10:51:38 : End Call TaskFunc(2)                       :同步调用,两个任务依次执行,总耗时4秒
            2018/9/25 10:51:38 : 程序结束
            ***********************************************************/
            private static void Test1()
            {
                TaskFunc(1);
                TaskFunc(2);
            }
    
            /***********************************************************
            2018/9/25 11:12:13 : 程序启动
            2018/9/25 11:12:13 : Begin Call TaskFunc(1)
            2018/9/25 11:12:13 : Begin Call TaskFunc(2)
            2018/9/25 11:12:15 : End Call TaskFunc(1)
            2018/9/25 11:12:15 : End Call TaskFunc(2)
            2018/9/25 11:12:15 : 程序结束                                   :主线程阻塞直到全部任务执行完毕
            ***********************************************************/
            // 并行运行的只有两个TaskFunc,主线程是阻塞的
            private static void Test2()
            {
                int[] a = new int[2] { 1, 2 };
                Parallel.ForEach(a, n => { TaskFunc(n); });
            }
    
            /***********************************************************
            2018/9/25 11:03:54 : 程序启动
            2018/9/25 11:03:54 : Begin Call TaskFunc(1)
            2018/9/25 11:03:54 : Begin Call TaskFunc(2)
            2018/9/25 11:03:56 : End Call TaskFunc(1)
            2018/9/25 11:03:56 : End Call TaskFunc(2)                       :两个任务同时开始同时结束,总耗时2秒
            2018/9/25 11:03:56 : 程序结束                                   :Task.WaitAll阻塞了主线程
            ***********************************************************/
            // 并行运行的只有两个TaskFunc,主线程是阻塞的,与Test2相同
            // 去掉Task.WaitAll,可以实现主线程、两个TaskFunc并行,但无法在两个TaskFunc完成后做些事情
            private static void Test3()
            {
                Task t1 = Task.Run(() => { TaskFunc(1); });
                Task t2 = Task.Run(() => { TaskFunc(2); });
                Task.WaitAll(t1, t2);
            }
    
            /***********************************************************
            2018/9/25 11:01:32 : 程序启动
            2018/9/25 11:01:32 : Begin Call TaskFunc(1)
            2018/9/25 11:01:32 : Begin Call TaskFunc(2)
            2018/9/25 11:01:34 : End Call TaskFunc(1)
            2018/9/25 11:01:34 : End Call TaskFunc(2)                       :两个任务同时开始同时结束,总耗时2秒
            2018/9/25 11:01:34 : 程序结束                                   :EndInvoke阻塞了主线程
            ***********************************************************/
            // 并行运行的只有两个TaskFunc,主线程是阻塞的,与Test2,Test3相同
            private static void Test4()
            {
                Action a1 = () => { TaskFunc(1); };
                Action a2 = () => { TaskFunc(2); };
                IAsyncResult iar1 = a1.BeginInvoke(null, null);
                IAsyncResult iar2 = a2.BeginInvoke(null, null);
                a1.EndInvoke(iar1);
                a2.EndInvoke(iar2);
            }
    
            /***********************************************************
            2018/9/25 17:05:08 : 程序启动
            2018/9/25 17:05:08 : 程序结束                                   :放在callback中的EndInvoke不会阻塞主线程
            2018/9/25 17:05:08 : Ticks
            2018/9/25 17:05:08 : Begin Call TaskFunc(1)
            2018/9/25 17:05:08 : Begin Call TaskFunc(2)
            2018/9/25 17:05:09 : Ticks
            2018/9/25 17:05:10 : Ticks
            2018/9/25 17:05:10 : End Call TaskFunc(1)
            2018/9/25 17:05:10 : End Call TaskFunc(2)                       :两个任务同时开始同时结束,总耗时2秒
            ***********************************************************/
            // 主线程、两个TaskFunc并行运行
            // 可以在AsyncCallback种添加TaskFunc结束后的代码,并且不会阻塞主线程
            private static void Test5()
            {
                Action a1 = () => { TaskFunc(1); };
                Action a2 = () => { TaskFunc(2); };
                a1.BeginInvoke(new AsyncCallback(iar => { a1.EndInvoke(iar); }), null);
                a2.BeginInvoke(new AsyncCallback(iar => { a2.EndInvoke(iar); }), null);
            }
    
            /***********************************************************
            2018/9/25 17:06:48 : 程序启动
            2018/9/25 17:06:48 : 程序结束                                   :await没有阻塞主线程
            2018/9/25 17:06:48 : Ticks
            2018/9/25 17:06:48 : Begin Call TaskFunc(2)
            2018/9/25 17:06:48 : Begin Call TaskFunc(1)
            2018/9/25 17:06:49 : Ticks
            2018/9/25 17:06:50 : Ticks
            2018/9/25 17:06:50 : End Call TaskFunc(1)
            2018/9/25 17:06:50 : End Call TaskFunc(2)
            2018/9/25 17:06:50 : End Call Test6()                           :阻塞异步调用,等待任务完成
            ***********************************************************/
            // 主线程、两个TaskFunc并行运行
            // await没有阻塞主线程,达到了Test5相似的功能,代码更简洁
            private static async void Test6()
            {
                Task t1 = Task.Run(() => { TaskFunc(1); });
                Task t2 = Task.Run(() => { TaskFunc(2); });
                await Task.WhenAll(t1, t2);
                Console.WriteLine(DateTime.Now.ToString() + " : " + "End Call Test6()");
            }
    
            /***********************************************************
            2018/9/25 17:10:20 : 程序启动
            2018/9/25 17:10:21 : Begin Call TaskFunc(1)
            2018/9/25 17:10:22 : Begin Call TaskFunc(2)
            2018/9/25 17:10:23 : 程序结束
            2018/9/25 17:10:23 : Ticks
            2018/9/25 17:10:23 : End Call TaskFunc(1)
            2018/9/25 17:10:24 : End Call TaskFunc(2)
            2018/9/25 17:10:24 : End Call Test6()
            2018/9/25 17:10:24 : Ticks
            2018/9/25 17:10:25 : Ticks
            2018/9/25 17:10:26 : Ticks
            2018/9/25 17:10:27 : End Call Test6()
            ***********************************************************/
            // await之前的Sleep阻塞了主线程,await之后的Sleep没有阻塞主线程
            private static async void Test7()
            {
                Thread.Sleep(1000);
                Task t1 = Task.Run(() => { TaskFunc(1); });
                Thread.Sleep(1000);
                Task t2 = Task.Run(() => { TaskFunc(2); });
                Thread.Sleep(1000);
                await Task.WhenAll(t1, t2);
                Console.WriteLine(DateTime.Now.ToString() + " : " + "End Call Test6()");
                Thread.Sleep(3000);
                Console.WriteLine(DateTime.Now.ToString() + " : " + "End Call Test6()");
            }
    
            /***********************************************************
            2018/9/25 17:14:01 : 程序启动
            2018/9/25 17:14:04 : Begin Call TaskFunc(1)
            2018/9/25 17:14:06 : End Call TaskFunc(1)
            2018/9/25 17:14:07 : Begin Call TaskFunc(2)
            2018/9/25 17:14:09 : End Call TaskFunc(2)
            2018/9/25 17:14:10 : End Call Test6()
            2018/9/25 17:14:13 : End Call Test6()
            2018/9/25 17:14:13 : 程序结束
            ***********************************************************/
            // 在await调用的时候,两个Task都已经结束了,await之后的Sleep也阻塞了主线程
            private static async void Test8()
            {
                Thread.Sleep(3000);
                Task t1 = Task.Run(() => { TaskFunc(1); });
                Thread.Sleep(3000);
                Task t2 = Task.Run(() => { TaskFunc(2); });
                Thread.Sleep(3000);
                await Task.WhenAll(t1, t2);
                Console.WriteLine(DateTime.Now.ToString() + " : " + "End Call Test6()");
                Thread.Sleep(3000);
                Console.WriteLine(DateTime.Now.ToString() + " : " + "End Call Test6()");
            }
        }
  • 相关阅读:
    WebStorm 简单部署服务器进行测试操作
    springbootstarterthymeleaf 避坑指南
    在linux云服务器上运行Jar文件
    springBoot整合MyBatise及简单应用
    关闭tomcat端口号
    基本项目框架搭建 sqlserver druid配置
    java springboot+maven发送邮件
    SQLServer 的存储过程与java交互
    Java 读写锁的实现
    SpringBoot 异步线程简单三种样式
  • 原文地址:https://www.cnblogs.com/zhuyingchun/p/9700621.html
Copyright © 2011-2022 走看看