IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> C# 多线程之Await和Async -> 正文阅读

[系统运维]C# 多线程之Await和Async

await/async语法

用同步的方式写异步回调

C#5 (.NET4.5) 引入的语法糖
C#7.1,Main入口也可以
C#8.0,可以使用异步流await foreach和可释放对象 await using

1 async 是用来修饰方法,如果单独出现,方法会警告,没有什么作用
2 await在方法体内部,只能放在async修饰的方法内,必须放在task前面
3 async/await方法里面如果没有返回值,默认返回一个Task,或者void(推荐用Task,而不是void,因为这样才能await/wait)
4 带async+await后,返回值要多一层Task<>

返回值void函数

主线程到await这里就返回了,执行主线程任务;
同时task的子线程就开始工作,直到Task完成,然后继续后续任务(后续任务的线程ID不一定是这个子线程,可以是子线程,也可以是其他线程,还可以是主线程);
效果上等价于continuewith。

        private static async void NoReturn()
        {
            //主线程执行
            Console.WriteLine($"NoReturn Sleep before await,ThreadId={Thread.CurrentThread.ManagedThreadId}");
            TaskFactory taskFactory = new TaskFactory();
            Task task = taskFactory.StartNew(() =>
            {
                Console.WriteLine($"NoReturn Sleep3000 before,ThreadId={Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(3000);
                Console.WriteLine($"NoReturn Sleep3000 after,ThreadId={Thread.CurrentThread.ManagedThreadId}");
            });
            //task.ContinueWith(t => //这是一个回调
            //{
            //    Console.WriteLine($"NoReturn Sleep after await,ThreadId={Thread.CurrentThread.ManagedThreadId}");
            //});

            await task;
            //主线程到await这里就返回了,执行主线程任务
            //同时task的子线程就开始工作,直到Task完成,然后继续后续任务(后续任务的线程ID不一定是这个子线程,可以是子线程,也可以是其他线程,还可以是主线程) 
            //像什么? 效果上等价于continuewith
            //task.ContinueWith(t =>
            //{
            //    Console.WriteLine($"NoReturn Sleep after await,ThreadId={Thread.CurrentThread.ManagedThreadId}");
            //});

            Console.WriteLine($"NoReturn Sleep after await,ThreadId={Thread.CurrentThread.ManagedThreadId}");
        }

返回值Task函数

无返回值 async Task == async void;
Task和Task< T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用。Async Void 不行。

        private static async Task NoReturnTask() //在async/await方法里面如果没有返回值,默认返回一个Task
        {
            //这里还是主线程的id
            Console.WriteLine($"NoReturnTask Sleep before await,ThreadId={Thread.CurrentThread.ManagedThreadId}");

            Task task = Task.Run(() =>
            {
                Console.WriteLine($"NoReturnTask Sleep3000 before,ThreadId={Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(1000);
                Console.WriteLine($"NoReturnTask Sleep3000 after,ThreadId={Thread.CurrentThread.ManagedThreadId}");
            });
            await task;
            Console.WriteLine($"NoReturnTask Sleep after await,ThreadId={Thread.CurrentThread.ManagedThreadId}");
            //return;
            //return new TaskFactory().StartNew(() => { });  //不能return  没有async才行
        }

返回值Task的函数

        /// <summary>
        /// 带返回值的Task  
        /// 要使用返回值就一定要等子线程计算完毕
        /// </summary>
        /// <returns>async 就只返回long</returns>
        private static async Task<long> SumAsync()
        {
            Console.WriteLine($"SumAsync 111 start ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
            long result = 0;

            await Task.Run(() =>
            {
                for (int k = 0; k < 10; k++)
                {
                    Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
                    Thread.Sleep(1000);
                }
                for (long i = 0; i < 999_999_999; i++)
                {
                    result += i;
                }
            });

            Console.WriteLine($"SumFactory 111   end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
            await Task.Run(() =>
            {
                for (int k = 0; k < 10; k++)
                {
                    Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
                    Thread.Sleep(1000);
                }
                for (long i = 0; i < 999999999; i++)
                {
                    result += i;
                }
            });
            Console.WriteLine($"SumFactory 111   end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");

            await Task.Run(() =>
            {
                for (int k = 0; k < 10; k++)
                {
                    Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
                    Thread.Sleep(1000);
                }

                for (long i = 0; i < 999999999; i++)
                {
                    result += i;
                }
            });

            Console.WriteLine($"SumFactory 111   end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");

            return result;
        }

调用如下:

                Task<long> t = SumAsync();
                Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
                long lResult = t.Result;//访问result,阻塞式   主线程等待所有的任务挖成 //如果访问Result,就相当于是同步方法!
                //t.Wait();//等价于上一行,阻塞式--同步
                //await t;//非阻塞,

没有Async和Await的函数

        /// <summary>
        /// 真的返回Task  不是async  
        /// 
        /// 要使用返回值就一定要等子线程计算完毕
        /// </summary>
        /// <returns>没有async Task</returns>
        private static Task<int> SumFactory()
        {
            Console.WriteLine($"SumFactory 111 start ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
            TaskFactory taskFactory = new TaskFactory();
            Task<int> iResult = taskFactory.StartNew<int>(() =>
            {
                Thread.Sleep(3000);
                Console.WriteLine($"SumFactory 123 Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
                return 123;
            });
            //Console.WriteLine($"This is {iResult.Result}");
            Console.WriteLine($"SumFactory 111   end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
            return iResult;
        }

其他

适合场景

跟第三方交互的(非托管资源,经常有async版本):

  • 数据库openAsync-Redis
  • Web请求-Api
  • 文件读取
    在这里插入图片描述

Await为什么能提升吞吐—只负责发命令—然后就忙别的去了—不需要等待—事儿完成前就不浪费资源—完成后再来线程处理—这里还能复用

不适合场景

服务器本地计算(CPU密集型,托管资源)

  • 大数据加减乘除,
  • 数据处理

反而可能影响性能,但是用了没啥事儿

总结

await/async是语法糖,同步方式写异步,增加系统吞吐量,一用到底,Web开发推荐

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-09-22 15:02:37  更:2021-09-22 15:03:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 16:53:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码