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

转载源:小宅博客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


    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#中的async和await关键字是用来实现异步编程的。它们的作用是让开发人员能够更方便地处理异步任务。async关键字可以用来修饰方法,表示该方法是一个异步方法,而await关键字用于等待异步任务的完成。 async和await的使用可以帮助我们编写更简洁、易读的异步代码。当我们在一个方法中使用了async关键字时,编译器会将该方法转换为一个状态机。这样,当遇到一个耗时的操作时,我们可以使用await关键字来等待该操作完成,而不会阻塞整个线程。当异步操作完成后,代码会继续执行。 async和await的使用需要注意一些细节。首先,异步方法必须返回一个Task对象或Task<T>对象,表示异步操作的结果。其次,在异步方法中,可以使用await关键字来等待一个异步操作的完成,但需要在方法的签名中声明async关键字。而且,await关键字只能在异步方法中使用。 在使用async和await时,还需注意一些原则。首先,尽量避免在异步方法中使用阻塞操作,以充分发挥异步编程的优势。其次,可以使用Task.WhenAll或Task.WhenAny等方法来并行处理多个异步任务。另外,可以使用ConfigureAwait方法来配置异步任务的上下文。 总之,C#中的async和await提供了一种简洁、易读的方式来处理异步任务。通过合理的使用,可以提高代码的性能和可维护性。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值