我的编程空间,编程开发者的网络收藏夹
学习永远不晚

关于C#中async/await的用法实例详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

关于C#中async/await的用法实例详解

一直对c#中async/await的用法模模糊糊,不太清晰,今天写了一下Demo彻底明确一下async/await的用法,以免因为对其不了解而对后期的业务产生影响(比如事务导致的锁表等等)。

1. 首先,async/await一般是成对出现才有意义。其意义在于可以等待异步操作完成后继续顺序执行,而不是异步操作还没处理完成主线程就进行了下一步。

假设,我们现在要模拟简单的下载场景,首先用户点击下载,那么就调用DownloadHandle方法(异步)进行下载,然后通知用户下载完成。其使用async/await的区别如下:

(1)使用async/await 的情况:

internal class Program
    {
        static void Main(string[] args)
        {
            DownloadHandle();
            Console.ReadLine();
        }
        /// <summary>
        /// 正常使用async/await时,符合正常的业务逻辑:
        /// 1. 通知用户下载开始
        /// 2. 异步下载
        /// 3. 等待异步下载完成后给用户提示下载完成
        /// </summary>
        public static async void DownloadHandle()
        {
            Console.WriteLine("下载开始!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);
            await Download();
            Console.WriteLine("下载完成!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);

        }
        /// <summary>
        /// 下载
        /// </summary>
        /// <returns></returns>
        public static Task Download()
        {
            return Task.Run(() =>
            {
                Console.WriteLine("下载线程ID:->" + Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine("10%");
                Console.WriteLine("30%");
                Console.WriteLine("50%");
                Console.WriteLine("60%");
                Console.WriteLine("80%");
                Console.WriteLine("99%");
                Console.WriteLine("100%");
            });
        }
    }

结果如下:

可以看到,即时下载使用了异步(线程ID不同也表明了当前使用了异步),业务逻辑最终还是按照我们的需求,按顺序正序执行了。

(2)不使用async/await的情况:

internal class Program
    {
        static void Main(string[] args)
        {
            DownloadHandle();
            Console.ReadLine();
        }
        /// <summary>
        /// 不适用async/await时,则代码执行顺序时混乱的,不符合业务逻辑:
        /// 1. 通知用户下载开始
        /// 2. 提示下载完成
        /// 3. 开始下载
        /// </summary>
        public static void DownloadHandle()
        {
            Console.WriteLine("下载开始!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);
            Download();
            Console.WriteLine("下载完成!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);

        }
        /// <summary>
        /// 下载
        /// </summary>
        /// <returns></returns>
        public static Task Download()
        {
            return Task.Run(() =>
            {
                Console.WriteLine("下载线程ID:->" + Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine("10%");
                Console.WriteLine("30%");
                Console.WriteLine("50%");
                Console.WriteLine("60%");
                Console.WriteLine("80%");
                Console.WriteLine("99%");
                Console.WriteLine("100%");
            });
        }
    }

结果如下:

可以看到,代码执行顺序混乱了,“下载完成” 跑到了 “下载线程ID” 前面去了,完全没有按照我们预期的顺序执行。

2. 如果可以await的方法不进行await,那将会怎样呢?

(1)如果被调用的异步方法内部使用了Task.Run,那结果可参考我们1中进行讲述的结果。开发者可根据实际需要来进行调用,如果异步方法的调用结果与其上下文逻辑没有严格的执行要求,则可以不进行await(比如记录日志等等)。反之,则需要加await。

(2)如果被调用的异步方法内部只是返回了Task.CompletedTask,即时使用了await/async实际上还是等于同步执行,如下图。

internal class Program
    {
        static void Main(string[] args)
        {
            DownloadHandle();
            Console.ReadLine();
        }
        /// <summary>
        /// 模拟下载
        /// </summary>
        public static async void DownloadHandle()
        {
            Console.WriteLine("下载开始!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);
            await Download();
            Console.WriteLine("下载完成!->主线程ID:" + Thread.CurrentThread.ManagedThreadId);

        }
        /// <summary>
        /// 下载
        /// </summary>
        /// <returns></returns>
        public static Task Download()
        {
            Console.WriteLine("下载线程ID:->" + Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine("10%");
            Console.WriteLine("30%");
            Console.WriteLine("50%");
            Console.WriteLine("60%");
            Console.WriteLine("80%");
            Console.WriteLine("99%");
            Console.WriteLine("100%");
            return Task.CompletedTask;
        }

结果如图:

可以看到,即使DonwloadHandle方法使用了await/async,还是进行了同步执行,并没有异步效果(可从所有线程ID相同看出)

3.小技巧: 异步方法的返回值类型一般都是Task或者Task<T>类型的,当返回值为Task时(即方法的返回值类型为void),我们可以直接return Task.Run(()=>{})(以下第一段代码),而不必awaitTask.Run(()=>{})(以下第二段代码),这样也可从一定程度上提高代码执行效率。

/// <summary>
        /// 下载
        /// </summary>
        /// <returns></returns>
        public static Task Download()
        {
            return Task.Run(() =>
            {
                Console.WriteLine("下载线程ID:->" + Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine("10%");
                Console.WriteLine("30%");
                Console.WriteLine("50%");
                Console.WriteLine("60%");
                Console.WriteLine("80%");
                Console.WriteLine("99%");
                Console.WriteLine("100%");
            });
        }
/// <summary>
        /// 下载
        /// </summary>
        /// <returns></returns>
        public static async Task Download()
        {
            await Task.Run(() =>
            {
                Console.WriteLine("下载线程ID:->" + Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine("10%");
                Console.WriteLine("30%");
                Console.WriteLine("50%");
                Console.WriteLine("60%");
                Console.WriteLine("80%");
                Console.WriteLine("99%");
                Console.WriteLine("100%");
            });
        }

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

关于C#中async/await的用法实例详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

关于C#中async/await的用法实例详解

这篇文章主要介绍了关于C#中async/await的用法,今天写一个demo彻底搞明白async/await的用法,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-02-08

Swift 中的 async/await ——代码实例详解

前言 async-await 是在 WWDC 2021 期间的 Swift 5.5 中的结构化并发变化的一部分。Swift 中的并发性意味着允许多段代码同时运行。这是一个非常简化的描述,但它应该让你知道 Swift 中的并发性对你的应用程序
2023-08-17

es7中的async、await使用方法示例详解

async、await是es7里面的新语法,async申明一个function是异步,而await等待一个异步方法执行完成。替代promise中的then。async函数返回一个Promise对象,当函数执行的时候,一旦遇到await就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。
2023-01-28

ES6中的Promise对象与async和await方法详解

Promise是es6引入的异步编程薪解决方案,语法上promise就是一个构造函数,用来封装异步操作病可以获取其成功或失败的结果,这篇文章主要介绍了ES6中的Promise对象与async和await方法,需要的朋友可以参考下
2022-12-29

关于C#中的Invoke示例详解

一直对invoke和begininvoke的使用和概念比较混乱,这两天看了些资料,对这两个的用法和原理有了些新的认识和理解,下面这篇文章主要给大家介绍了关于C#中Invoke的相关资料,需要的朋友可以参考下
2023-02-06

关于promise和async用法以及区别详解

Promise是一个构造函数,我们就可以newPromise()得到一个Promise的实例,下面这篇文章主要给大家介绍了关于promise和async用法以及区别的相关资料,需要的朋友可以参考下
2023-01-10

C++的optional用法实例详解

optional是C++标准库中的模板类,表示值存在或不存在。它用于处理可能为null或未初始化的指针和引用,通过has_value()判断值是否存在,使用value()获取值(如果存在)。optional用法实例包括处理可能为null的指针、缺少的参数、为零的值和嵌套optional。其好处在于明确null值处理、提高可读性、增强安全性和可扩展性。
C++的optional用法实例详解
2024-04-02

C#中关于double.ToString()的用法

这篇文章主要介绍了C#中关于double.ToString()的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-02-26

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录