C# Async与Await 同步与异步操作

C# 中的AsyncAwait 的用法详解 阅读详情

转载源:小宅博客C#第30节:http://www.bilibili996.com/Course?id=4688450000043

源码下载地址,提取码:sa4x
https://pan.baidu.com/s/109_JBTGTjUXVFS4cewEOuA

关于Async与Await的详细介绍

一、什么是异步

同步和异步主要用于修饰方法。
当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法;
当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务,调用者不用等待该方法执行完毕,我们称这个方法为异步方法。

异步的好处在于非阻塞(调用线程不会暂停执行去等待子线程完成),因此我们把一些不需要立即使用结果、较耗时的任务设为异步执行,可以提高程序的运行效率。
net4.0在ThreadPool的基础上推出了Task类,微软极力推荐使用Task来执行异步任务,现在C#类库中的异步方法基本都用到了Task;
net5.0推出了async/await,让异步编程更为方便。本篇主要介绍Task、async/await相关的内容,其他异步操作的方式会在下一篇介绍。

二、Task介绍

Task是在ThreadPool的基础上推出的,我们简单了解下ThreadPool。

ThreadPool中有若干数量的线程,如果有任务需要处理时,会从线程池中获取一个空闲的线程来执行任务,任务执行完毕后线程不会销毁,而是被线程池回收以供后续任务使用。

当线程池中所有的线程都在忙碌时,又有新任务要处理时,线程池才会新建一个线程来处理该任务,如果线程数量达到设置的最大值,任务会排队,等待其他任务释放线程后再执行。线程池能减少线程的创建,节省开销.

三、async/await介绍

async/await是基于Task的,而Task是对ThreadPool的封装改进,主要是为了更有效的控制线程池中的线程(ThreadPool中的线程,我们很难通过代码控制其执行顺序,任务延续和取消等等);

ThreadPool基于Thread的,主要目的是减少Thread创建数量和管理Thread的成本。

async/await Task是C#中更先进的,也是微软大力推广的特性,我们在开发中可以尝试使用Task来替代Thread/ThreadPool,处理本地IO和网络IO任务是尽量使用async/await来提高任务执行效率。

四、项目案例:

效果如下:
在这里插入图片描述

代码如下:

using System;
using System.Collections.Generic;
using System.Text;

namespace WindowsFormsApp
{
    public class Contents
    {
        public static readonly IEnumerable<string> WebSites = new string[]
        {
            "https://www.zhihu.com",
            "https://www.baidu.com",
            "http://www.bilibili996.com/Course?id=4688450000043"
            //"https://www.weibo.com",  //有些地址进行了反爬,或者失效了,无法访问
            //"https://www.stackoverflow.com",
            //"https://docs.microsoft.com",
            //"https://docs.microsoft.com/aspnet/core",
            //"https://docs.microsoft.com/azure",
            //"https://docs.microsoft.com/azure/devops",
            //"https://docs.microsoft.com/dotnet",
            //"https://docs.microsoft.com/dynamics365",
            //"https://docs.microsoft.com/education",
            //"https://docs.microsoft.com/enterprise-mobility-security",
            //"https://docs.microsoft.com/gaming",
            //"https://docs.microsoft.com/graph",
            //"https://docs.microsoft.com/microsoft-365",
            //"https://docs.microsoft.com/office",
            //"https://docs.microsoft.com/powershell",
            //"https://docs.microsoft.com/sql",
            //"https://docs.microsoft.com/surface",
            //"https://docs.microsoft.com/system-center",
            //"https://docs.microsoft.com/visualstudio",
            //"https://docs.microsoft.com/windows",
            //"https://docs.microsoft.com/xamarin"
        };
    }
}





using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp
{
    public partial class Form1 : Form
    {
        private readonly HttpClient httpClient = new HttpClient();

        public Form1()
        {
            InitializeComponent();
        }

        //窗体加载事件
        private void Form1_Load(object sender, EventArgs e)
        {
            //清空文本框内容
            textBox1.Text = "";
        }

        //点击同步加载
        private void button1_Click(object sender, EventArgs e)
        {
            //清空文本框
            //textBox1.Text = "";
            //程序开始时间
            var stopwatch = Stopwatch.StartNew();
            //同步加载地址信息
            DownloadWebsitesSync();
            //加载文本信息
            textBox1.Text += $"同步加载效果如上: Elapsed time: {stopwatch.Elapsed}{Environment.NewLine}";
            textBox1.Text += "=================================================================================";
        }

        //点击异步加载
        private async void button2_Click(object sender, EventArgs e)
        {
            //清空文本框
            //textBox1.Text = "";
            //程序开始时间
            var stopwatch = Stopwatch.StartNew();
            //异步加载文本信息
            await DownloadWebsitesAsync();
            //加载文本信息
            textBox1.Text += $"异步加载效果如上: Elapsed time: {stopwatch.Elapsed}{Environment.NewLine}";
            textBox1.Text += "=================================================================================";
        }

        //拼接文本内容
        private void ShowLog(string result)
        {
            textBox1.Text += $"\n{result}\n";
        }

        #region Button1同步加载
        private void DownloadWebsitesSync()
        {
            //遍历地址容器
            foreach (var site in Contents.WebSites)
            {
                var result = DownloadWebSiteSync(site);
                ShowLog(result);
            }
        }

        //返回同步请求地址结果
        private string DownloadWebSiteSync(string url)
        {
            //httpClient get请求地址,获取返回值
            var response = httpClient.GetAsync(url).GetAwaiter().GetResult();
            var responsePayloadBytes = response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();
            //返回请求结果
            return $"Finish downloding data from {url}. Total bytes returned {responsePayloadBytes.Length}. {Environment.NewLine}";
        }
        #endregion

        #region Button2异步加载
        private async Task DownloadWebsitesAsync()
        {
            //承载Task<string>容器
            List<Task<string>> downloadwebTasks = new List<Task<string>>();
            //遍历地址容器
            foreach (var site in Contents.WebSites)
            {
                downloadwebTasks.Add(DownloadWebsitesAsync(site));
                //var result = await Task.Run(() => DownloadWebSiteSync(site));
                //ShowLog(result);
            }
            var res = await Task.WhenAll(downloadwebTasks);
            foreach (var item in res)
            {
                ShowLog(item);
            }
        }

        //返回异步请求地址结果
        private async Task<string> DownloadWebsitesAsync(string url)
        {
            var response = await httpClient.GetAsync(url);
            var responsePayloadBytes = await response.Content.ReadAsByteArrayAsync();
            return $"Finish downloading data form {url}. Total bytes returned {responsePayloadBytes.Length}. {Environment.NewLine}";
        }
        #endregion


    }
}
C#await常用扩展方法 一起使用,用于异步方法中等待异步操作的完成,并且在异步操作完成后,恢复执行该方法。关键字的作用是将异步操作的等待转换为对异步结果的处理,使得异步编程更加简洁可读。中用于等待异步操作完成的关键字。对象的异步方法完成。方法可以等待多个任务中的任意一个完成。await 关键字用于等待一个返回。表达式返回其结果(如果有的话)。方法可以等待多个任务全部完成。结合,可以实现异步操作的取消。来捕获异步操作中的异常。 阅读详情

相关推荐

C#awaitasync的用法(一)

C# 中,await关键字用于异步编程,配合async方法一起使用。await允许你等待异步操作完成,而不会阻塞当前线程。简而言之,await会暂停当前方法的执行,直到任务完成,然后继续执行。async

qq_42880092的博客 1018

深入解析C#异步编程:await 关键字背后的实现原理

本文将带你深入了解 await 关键字的实现原理,从编译器生成的状态机到回调函数的注册触发,再到异步方法的生命周期管理。通过详细的代码示例流程图,我们将逐步解析异步方法的每一个步骤,帮助你更好地理解优化异步代码。

Bob的博客 2880

Taskasync/await(进阶篇&小白易懂版)

C#同步异步是两种不同的编程模式,用于控制代码的执行方式。同步模式是指代码按照从上到下的顺序依次执行,在执行一个任务时会一直阻塞在那里等待其完成。而异步模式则是指在调用一个任务后立即返回,不会等待这个任务完成,而是通过回调机制在任务完成时通知调用者,可以同时执行多个任务,提高程序的效率。使用场景:当你有一些可能会阻塞线程(如IO操作、网络请求、复杂计算等)的操作时,可以将它们封装为任务,并使用Task类来异步执行它们。这样可以避免阻塞UI线程或其他重要线程,提高应用程序的响应性性能。

2401_82410658的博客 4959

C# async/await 异步全解:从入门到实战,解决 90% 新手异步

同步,就是 “排队执行”。你去奶茶店点单,必须等前面的人点完、奶茶做好,你才能走。// 同步代码:先执行A,再执行B,界面卡死// 模拟耗时操作:下载文件// 卡5秒MessageBox.Show("下载完成");耗时操作阻塞了主线程,界面直接 “假死”。

dhdnsjsj的博客 508

C# async / await 用法

await 运算符暂停对其所属的 async 方法的求值,直到其操作数表示的异步操作完成。异步操作完成后,await 运算符将返回操作的结果(如果有)。当 await 运算符应用到表示已完成操作操作数时,它将立即返回操作的结果,而不会暂停其所属的方法。await 运算符不会阻止计算异步方法的线程。当 await 运算符暂停其所属的异步方法时,控件将返回到方法的调用方。下面来做一个演示,点击按钮1开始启动异步,点击按钮2,就返回结果,如果不点击按钮2,那么异步一直在循环中。

熊思雨的博客 2万+

C#异步编程(asyncawait)

异步编程的核心是TaskTask对象,这两个对象对异步操作建模。它们受关键字asyncawait的支持。在大多数情况下模型十分简单:对于 I/O 绑定代码,等待一个在async方法中返回Task或Task的操作。对于 CPU 绑定代码,等待一个使用Task.Run方法在后台线程启动的操作。通过使用异步编程,可以避免性能瓶颈并增强应用程序的总体响应能力。但是,编写异步应用程序的传统技术可能比较复杂,使它们难以编写、调试维护。C# 5 引入了一种简便方法,即异步编程。

风清扬的专栏 8717

关于c#异步asyncawait的理解

之前给大家介绍了所谓异步编程的用法,但是没有细致的理解到,今天想大家一起探讨一下;

wuyi的个人博客 1978

C# 异步Async/await

该文章仅为个人理解,如有错误请指正,标红内容为重点,会有针对异步的多个文章,包含Task,APM(BeginInvoke,EndInvoke)等。 一、基本概念: Async/await 关键字是在.Net 4.5引入的关键字来创建自动延续任务实现异步调用。 async/await是语法糖,等价于task.Run().ContinueWith(action,Task.FromCurrentS...

窝。。。 2072

关于异步async await

前端async await 今日学习了async await异步调用方法,先单独分析async作为一个关键字放在函数的前面,表示该函数是一个异步函数,意味着该函数的执行不会阻塞后面代码的执行,异步函数的调用跟普通函数一样。async的内部实现原理就是如果该函数中有一个返回值,当调用该函数时,默认会在内部调用Promise.solve() 方法把它转化成一个Promise 对象作为返回,若函数内部抛出错误,则调用Promise.reject()返回一个Promise 对象。 再分析await即等待

学习之路,创业之光 477

C#异步编程Async await实践理解

真理: 方法中没有await异步方法实质上是一个同步的方法 异步方法本身不会创建新的线程,但一般实现异步需要有新的线程去做一些事情 同一个异步方法中多个await的代码是同步执行的 异步方法实践 本文示例通过Test工程展现,控制台程序同理 初识异步的困惑&解惑 为啥我写的异步没用?还是同步执行的? [TestClass] public class AsyncTest { [TestMethod] public void Main()

hynkoala的博客 1503

C#多线程异步(二)——Taskasync/await详解

一、什么是异步   同步异步主要用于修饰方法。当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法;当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务,调用者不用等待该方法执行完毕,我们称这个方法为异步方法。   异步的好处在于非阻塞(调用线程不会暂停执行去等待子线程完成),因此我们把一些不需要立即使用结果、较耗时的任务设为异步执...

banyongzhan5405的博客 1741

C# Task async await多线程使用

C#多线程异步(二)——Taskasync/await详解 </h1> <div class="clear"></div> <div class="postBody"> 阅读目录一、什么是异步二、Task介绍1 Task创建...

weixin_43277501的博客 1389

浅析 C# 异步编程:async await

摘要:本文通过生活场景引入同步异步编程概念,详细讲解了C#async/await的工作原理。作者首先用同步代码示例展示阻塞式等待,然后将其改造为异步版本,重点解析await如何在不阻塞线程的情况下暂停恢复方法执行。文章还提供了一个完整的异步"点外卖"示例,对比同步异步实现的时间效率差异,并澄清了"await等待的是可等待表达式而非async方法"的常见误区。通过生活化类比代码示例,帮助读者理解异步编程的核心机制优势。

u011550456的博客 806

AsyncAwait关键字

本文介绍了C#asyncawait关键字的使用方法。async用于标记异步方法,await用于等待异步操作完成。同步方法在执行耗时IO操作时会阻塞主线程,导致UI无响应。通过将同步方法改为异步方法(使用Task.Run),可以避免阻塞主线程。关键在于: 异步方法必须返回Task或Task<T>类型 await会暂停当前方法执行但不阻塞线程 不加await异步方法会立即返回,导致后续代码提前执行 添加await能确保异步操作完成后再执行后续代码 示例展示了同步异步的不同效果,异步方式能保持

weixin_44710358的博客 1093

C#异步编程之async/await

在启动时看到大量并发请求的web应用中,或具有突发负载(其中并发增长突然增加)时,使web服务器调用异步会提高应用程序的相应能力。因此,当有多个并发请求调用长时间运行的操作时,异步请求会组织请求队列线程池的增长。但使用异步编程,可以提高响应能力(吞吐量),即使用异步方式在同一时间可以处理更多的请求。成对出现的方法是异步方法,那哪来的同步呢?如果以同步方式处理请求,则处理请求的线程将在处理请求时处于繁忙状态,并且该线程无法处理其他请求。相对主线程来说,是异步去执行的,但这个异步也是按顺序来的。

极客神殿 2534

Taskasync/await详解

一、什么是异步   同步异步主要用于修饰方法。当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法;当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务,调用者不用等待该方法执行完毕,我们称这个方法为异步方法。   异步的好处在于非阻塞(调用线程不会暂停执行去等待子线程完成),因此我们把一些不需要立即使用结果、较耗时的任务设为异步执...

weixin_30700977的博客 393

C# 彻底搞懂async/await

关键: 异步方法:在执行完成前立即返回调用方法,在调用方法继续执行的过程中完成任务。 async/await 结构可分成三部分: (1)调用方法:该方法调用异步方法,然后在异步方法执行其任务的时候继续执行; (2)异步方法:该方法异步执行工作,然后立刻返回到调用方法; (3)await 表达式:用于异步方法内部,指出需要异步执行的任务。一个异步方法可以包含多个 await 表达式(不存在 await 表达式的话 IDE 会发出警告)。 一、What's 异步? ...

lxrj2008的专栏 1万+
上一篇: WPF入门1:Application介绍与三种自定义启动程序代码
下一篇: WPF入门2:Grid网格布局
黄瓜炒鸡蛋emm
博客等级 码龄7年 318粉丝 · 90原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值