C# async / await 的使用方法

news2025/1/14 17:56:49

目录

一、简介

二、异步等待返回结果

三、异步方法的返回类型

四、await foreach

五、Task.Delay

结束


一、简介

await 运算符暂停对其所属的 async 方法的求值,直到其操作数表示的异步操作完成。 异步操作完成后,await 运算符将返回操作的结果(如果有)。 当 await 运算符应用到表示已完成操作的操作数时,它将立即返回操作的结果,而不会暂停其所属的方法。 await 运算符不会阻止计算异步方法的线程。 当 await 运算符暂停其所属的异步方法时,控件将返回到方法的调用方。

二、异步等待返回结果

下面就演示 await 运算符常用的一些用法。

新建一个基于 .Net6 的 Winform 项目,界面就两个按钮,如下:

代码 

namespace 异步编程
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            IsTrue = false;
            AwaitEnd();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            IsTrue = true;
        }


        private bool IsTrue = false; 
        private Task<string> StartTimer()
        {
            var t = Task.Run(() =>
            {
                while (true)
                {
                    if (IsTrue)
                        return "555";
                    Thread.Sleep(100);
                }
            });
            return t;
        }

        private async void AwaitEnd()
        {
            Console.WriteLine("开始执行,时间:" + DateTime.Now.ToString());
            var res = await StartTimer();
            Console.WriteLine("结束:" + res + " 时间:" + DateTime.Now.ToString());
        }
    }
}

点击按钮1开始启动异步,点击按钮2,就返回结果,如果不点击按钮2,那么 while 循环就不会停止。

效果:

可以看到,点击了按钮1后,并不会让主线程卡死,窗体还是可以随意的拖动的,直到 StartTimer 方法将返回值返回回来后,才会继续执行后续的代码,这对一些需要阻塞线程,并获取另外的计算结果,然后才能继续计算的需求而言,有极大的帮助,比如读取数据库数据,如果网速比较慢,并且不会立刻就返回结果,用 await 运算符就可以在同一个方法里,等到获取到数据库返回结果后,再进行下一步运算,而不是从上到下,一下子就执行完了。

下面是以前我查询数据库写的代码,效果和上面演示中的 await 运算符是一样的,在下面的方法中,使用 Action 回调,代码都没写到一起,虽然逻辑一样,但用起来就不是那么的方便。

/// <summary>
/// 执行SQL语句,并获取值
/// </summary>
/// <param name="sql"></param>
/// <param name="callBack"></param>
private static void ExecuteAndReturnValue(string sql, Action<DataTable?> callBack)
{
    Func<DataTable?> Funcs = () =>
    {
        DataSet dataSet = MySqlHelper.GetDataSet(sql);
        if (dataSet == null || dataSet.Tables.Count == 0)
            return null;
        return dataSet.Tables[0];
    };

    //执行任务
    Task<DataTable?> printRes = Task.Run(Funcs);

    //等待任务完成
    printRes.GetAwaiter().OnCompleted(() =>
    {
        if (callBack != null)
            callBack(printRes.Result);
    });
}

当前的示例,只是执行单个任务,如果有多个任务,用下面的方法也是可以的,

private Task DoSomethingAsync(int x)
{
    return Task.Run(() =>
    {
        Thread.Sleep(1000);
        Console.WriteLine("值:" + x);
    });
}

public async Task RunAsync()
{
    foreach (var x in new[] { 1, 2, 3 })
    {
        await DoSomethingAsync(x);
    }
}

DoSomethingAsync 方法中,返回值可以从另一个数组中获取到 Task 并执行,我这里就不写那么仔细了,如果用面向过程的写法,就是这么写的:


private async void Test()
{
    await Task.Run(async () =>
    {
        await Task.Delay(4000);
        Trace.WriteLine("第1个线程执行");
    });
    await Task.Run(async () =>
    {
        await Task.Delay(3000);
        Trace.WriteLine("第2个线程执行");
    });
    await Task.Run(async () =>
    {
        await Task.Delay(2000);
        Trace.WriteLine("第3个线程执行");
    });
}

三、异步方法的返回类型

在方法里加上了 async 关键字后,返回值就只能使用固定的几个了,不然会报错。

异步函数的返回类型只能为: void、Task、Task<TResult>、ValueTask 或 ValueTask<TResult>

Task<TResult>: 代表一个返回值T类型的操作。

Task: 代表一个无返回值的操作。

void: 为了和传统的事件处理程序兼容而设计。

四、await foreach

可以使用 await foreach 语句来使用异步数据流,即实现 IAsyncEnumerable<T> 接口的集合类型。 异步检索下一个元素时,可能会挂起循环的每次迭代。

代码

private async void Test()
{
    IAsyncEnumerable<int> pullBasedAsyncSequence = ProduceAsyncSumSeqeunc(5);
    //开始另一项任务;用于使用异步数据序列!
    var consumingTask = Task.Run(() => ConsumeAsyncSumSeqeunc(pullBasedAsyncSequence));
    
    await Task.Delay(TimeSpan.FromSeconds(3));
    Console.WriteLine("搞一些其他事");

    //只是为了演示!等待任务完成!
    await consumingTask;

    Console.WriteLine("异步流演示完成!" );
}

private async Task ConsumeAsyncSumSeqeunc(IAsyncEnumerable<int> sequence)
{
    Console.WriteLine("执行 ConsumeAsyncSumSeqeunc 方法");

    await foreach (var value in sequence)
    {
        Console.WriteLine($"value: {value}");

        await Task.Delay(TimeSpan.FromSeconds(1));
    };
}

private async IAsyncEnumerable<int> ProduceAsyncSumSeqeunc(int count)
{
    Console.WriteLine("执行 ProduceAsyncSumSeqeunc 方法");
    int index = 0;
    for (int i = 0; i < count; i++)
    {
        await Task.Delay(TimeSpan.FromSeconds(0.5));
        yield return index += count;
    }
}

调用 Test 方法后,即可打印

五、Task.Delay

解释:创建将在时间延迟后完成的任务。命名空间: System.Threading.Tasks

在上面的演示中用到了多次,例:

await Task.Delay(TimeSpan.FromSeconds(0.5));

在 Delay 方法中,可以用 TimeSpan 中的时、分、秒 表示

参考:

Delay(Int32)

创建一个在指定的毫秒数后完成的任务。

Delay(TimeSpan)

创建一个在指定的时间间隔后完成的任务。

Delay(Int32, CancellationToken)

创建一个在指定的毫秒数后完成的可取消任务。

Delay(TimeSpan, CancellationToken)

创建一个在指定的时间间隔后完成的可取消任务。

结束

如果这个帖子对你有所帮助,欢迎 关注 、点赞 、留言

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/10580.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Xilinx】Zynq\MPSoc\Versal不同速度等级下的ARM主频

【Xilinx】Zynq\MPSoc\Versal不同速度等级下的ARM主频一、Zynq&#xff08;A9&#xff09;二、MPSoC(A53R5)三、Versal(A72R5F)最近有很多人在选型的时候&#xff0c;问到ARM主频的问题&#xff0c;不知道去哪里找这个参数。 授人以鱼不如授人以渔&#xff0c;基本的通用方法是…

【面试题】 TypeScript 前端面试题 由浅到深

给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 基本类型介绍 1.Boolean&#xff0c;Number&#xff0c;String 声明:类型 类型对应变量 let flag:boolean true let …

【现代密码学原理】——哈希函数(学习笔记)

&#x1f4d6; 前言&#xff1a;我们在登录QQ有时会遇到密码忘记的问题&#xff0c;那么思考一下&#xff0c;为什么腾讯公司不直接把密码发还给用户而是要求设置新密码呢。其实&#xff0c;不保存密码&#xff0c;是为了更好地对密码保密&#xff0c;换言之&#xff0c;腾讯的…

力扣(LeetCode)106. 从中序与后序遍历序列构造二叉树(C++)

递归 如图&#xff0c;后序序列按照左右根遍历&#xff0c;所以根在最后。逆着后序遍历的顺序&#xff0c;按照根右左递归建树就可以复原这棵树。后序序列&#xff0c;可以确定根的位置 postrootpostrootpostroot 和根结点的值。我们在中序序列找到根结点的值&#xff0c;就确定…

《深度学习进阶 自然语言处理》第四章:Embedding层和负采样介绍

文章目录4.1 word2vec的改进一4.1.1 Embedding层4.2 word2vec的改进二4.2.1 中间层之后的计算问题4.2.2 从多分类到二分类4.2.3 负采样总结之前文章链接&#xff1a; 开篇介绍&#xff1a;《深度学习进阶 自然语言处理》书籍介绍 第一章&#xff1a;《深度学习进阶 自然语言处…

想知道有没有拍照转文字的软件?这3款工具职场人士必备

你们在工作上有没有遇到这种情况&#xff0c;就是领导突然甩一份纸质文件给你&#xff0c;并要求整理成电子版&#xff0c;供其他同事查阅。回想我当初刚踏入职场时&#xff0c;没有什么工作经验&#xff0c;只会对照着内容手动码字输出&#xff0c;但是太浪费时间了&#xff0…

湖北银行冲刺上市:不良率高于行业均值,有公司欠5亿元未能追回

撰稿|汤汤 来源|贝多财经 最近&#xff0c;湖北银行正式向A股递交申请材料&#xff0c;准备在上海证券交易所上市。 据贝多财经了解&#xff0c;湖北银行股份有限公司&#xff08;下称“湖北银行”&#xff09;于2022年11月4日在证监会预披露招股书&#xff0c;计划在上交所…

Azide-PEG-Aldehyde,N3-PEG-ALD,叠氮-PEG-醛基可用于新材料研究

化学试剂叠氮-聚乙二醇-醛基&#xff0c;其英文名为Azide-PEG-Aldehyde&#xff08;N3-PEG-ALD&#xff09;&#xff0c;它所属分类为Aldehyde / Acetal PEG Azide PEG。 peg试剂的分子量均可定制&#xff0c;有&#xff1a;5000 N3-PEG-ALD、10000 叠氮-PEG-醛基、1000 N3-PE…

短视频社交|电影点播平台Springboot+vue+ElementUI前后端分离

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…

SpringMVC 请求流程源码分析

三哥 内容来自【自学星球】 欢迎大家来了解我的星球&#xff0c;和星主&#xff08;也就是我&#xff09;一起学习 Java &#xff0c;深入 Java 体系中的所有技术。我给自己定的时间是一年&#xff0c;无论结果如何&#xff0c;必定能给星球中的各位带来点东西。 想要了解更多&…

使用robot+selenium创建一个UI自动化测试用例

新建项目并安装robotframework pip install robotframework 在pycharm-插件&#xff0c;输入robot搜索插件 选择Robot Framework Language Server或者Hyper RobotFramework Support安装 新建test.robot文件编写测试用例test.robot robot用例文件通常包括4个头部分&#xf…

Substance Painter 的一些玩法笔记

Substance Painter 的一些玩法 1、模型边缘磨损效果&#xff1a; 参考连接&#xff1a;Substance Painter 后期添加法线贴图&#xff0c;处理边缘磨损&#xff01;_哔哩哔哩_bilibili 使用方法&#xff1a; 1、导入要处理的模型文件 2、烘焙 模型贴图(主要是法线) 3、创建一个…

接口api 之Swagger 一次实战探索

今天我们来说说什么是Swagger&#xff1f; 就是把相关的信息存储在它定义的描述文件里面&#xff08;yml或json格式&#xff09;&#xff0c;再通过维护这个描述文件可以去更新接口文档&#xff0c;以及生成各端代码。而Springfox-swagger,则可以通过扫描代码去生成这个描述文…

自学CFD:我在实习岗速成无人机设计和仿真的故事

一、写在前面 大家好&#xff0c;我叫Jack&#xff08;硕士在读&#xff09;&#xff0c;目前在企业实践学习。 作为一名门外汉&#xff0c;初识计算流体力学&#xff0c;经历了盲目无措、乱做一气&#xff0c;查资料找经验毫无进展&#xff0c;直到从B站遇到了Graychen老师。…

综合布线工程测试技术

一、测试的相关基础知识 综合布线工程测试内容主要包括三个方面:工作区到设备间的连通状况测试、主干线连通状况测试、跳线测试。 每项测试内容主要测试以下参数:信息传输速率、衰减、距离、接线图、近端串扰等。 1、接线图(Wire Map) 接线图是用来检验每根电缆末端…

24、四大函数式接口(有函数型接口和断定型接口(都是函数式接口))

四大函数式接口&#xff08;有函数型接口和断定型接口&#xff08;都是函数式接口&#xff09;&#xff09; 新时代程序员&#xff1a;lambda表达式&#xff0c;链式编程&#xff0c;函数式接口&#xff0c;Stream流式计算 函数式接口&#xff1a;只有一个抽象方法的接口&…

热门Java开发工具IDEA入门指南——从Eclipse迁移到IntelliJ IDEA(二)

IntelliJ IDEA&#xff0c;是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的java开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能是非常强大的。 本文…

HTML非遗文化网页设计题材【京剧文化】HTML+CSS(大美中国 14页 带bootstarp)

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 茶文化网站 | 中华传统文化题材 | 京剧文化水墨风书画 | 中国民间年画文化艺术网站 | 等网站的设计与制作 | HTML期末大学生网页设计作业&#xff0c;…

Publisher/Subscriber 订阅-发布模式原理解析

Publisher/Subscriber 订阅-发布模式原理解析 参考资料 What Is Pub/Sub? Publish/Subscribe Messaging Explained什么是serverless&#xff1f;Pub/Sub Examples: 5 Use Cases to Understand the Pattern and its BenefitsJavaScript 设计模式精讲Avro Schema格式 一、概念…

【视觉高级篇】21 # 如何添加相机,用透视原理对物体进行投影?

说明 【跟月影学可视化】学习笔记。 如何理解相机和视图矩阵&#xff1f; 用一个三维坐标&#xff08;Position&#xff09;和一个三维向量方向&#xff08;LookAt Target&#xff09;来表示 WebGL 的三维世界的一个相机。要绘制以相机为观察者的图形&#xff0c;需要用一个…