c#异步编程

简介: c#异步编程原理,await asnyc的使用方法。异步编程是指在程序执行过程中,不需要等待某个操作完成,就可以继续执行后续的代码。

 异步编程是指在程序执行过程中,不需要等待某个操作完成,就可以继续执行后续的代码。比如我们开发了一个web页面中有一个上传文件功能,我们上传文件时使用异步操作,就不用等待文件的上传时间,可以先在网页上进行其他操作。但是如果我们的需求是等待上传文件完成之后才能进行下一步操作,比如我在boss上上传简历,然后根据附件简历生成在线简历,然后我在对在线简历进行优化,这时候就需要加一个await等待这个异步完成。

下面使用代码来举一个例子

创建一个 100000000个a 的超长字符串,然后把这个字符串写进d盘的文本里面

public static async Task Main(string[] args)
{
    string str = new string('a', 100000000);
    await File.WriteAllTextAsync("d:/1.txt", str);//加了await的异步写入
    File.WriteAllTextAsync("d:/2.txt", str);//异步写入
    File.WriteAllText("d:/3.txt", str);
}

image.gif

打个断点 ,一步一步来执行

image.gif编辑

执行完第一行写入到d盘的1.txt时 ,d盘已经有了一个记事本,有很多的a,因为这句代码加了await,这里会等它执行完再到下一步。

image.gif编辑

接着往下走,执行到最后一行代码时,虽然D盘也有2.txt了,但是由于我没有加await,此时并没有等第三句代码执行完。所以这个断点往下走时我们会发现并不会像上面一样等很久,因为异步方法会立刻返回到调用者,因此也叫(非阻塞方法)

image.gif编辑

可以看到记事本中有很多的a,但是很显然没有 100000000个,很显然是写到一半被我的断点停住了。

image.gif编辑

把断点继续,此时最后两句代码一起在执行,分别往2.txt和3.txt写入。

在上面的方法中加入打印线程,看一下执行过程线程的变化

string str = new string('a', 100000000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
await File.WriteAllTextAsync("d:/1.txt", str);//加了await的异步写入
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
File.WriteAllTextAsync("d:/2.txt", str);//异步写入
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
File.WriteAllText("d:/3.txt", str);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

image.gif

image.gif编辑

打印结果显示,加了await的异步方法执行完后线程发生了变化 ,因为原有线程遇见await会被解放,用于执行异步任务的线程会在任务完成后返回到await处接替原有线程继续执行任务

再举一个例子,我们自己创建一个异步方法

public static  async Task MethodAsync()
{  
    await Task.Run(() =>
    {  
        for (int i = 0; i < 1000; i++)
        {  
            Console.WriteLine(" MethodAsync   "+i);  
        }  
            Console.WriteLine("异步线程=====>"+Thread.CurrentThread.ManagedThreadId);
    });  
}

image.gif

再创建一个普通方法

public static void Method()
    {  
        for (int i = 0; i < 1000; i++)
        {  
            Console.WriteLine(" Method    " +i);  
        }  
            Console.WriteLine("普通方法线程=====>"+Thread.CurrentThread.ManagedThreadId);
    }

image.gif

在main方法中使用await调用异步方法

public static async Task Main(string[] args)
    {
        Console.WriteLine("线程main =====>"+Thread.CurrentThread.ManagedThreadId);
        await MethodAsync();
        Console.WriteLine("线程main=====>"+Thread.CurrentThread.ManagedThreadId);
        Method();
        Console.WriteLine("线程main=====>"+Thread.CurrentThread.ManagedThreadId);
    }

image.gif

把方法停在普通方法前

image.gif编辑

控制台输出👇

image.gif编辑image.gif编辑

因为加了await,所以等待异步方法for循环完成,从控制台输出结果看出,main方法一开始的线程是1,在执行异步方法时线程是3,执行完异步方法后回到main方法,打印线程还是3,因此上面提到的

原有线程遇见await会被解放,用于执行异步任务的线程会在任务完成后返回到await处接替原有线程继续执行任务

这句话成立。

那我们再试试不加await的

image.gif编辑

还是一样停在刚刚的断点处,可是此时的两次主线程打印都是1,异步方法还没开始打印

image.gif编辑

继续往下走,在控制台中发现,异步方法中新开了一个线程3,和普通方法交叉打印,最后打印主方法的线程也是原来的线程。

image.gif编辑

image.gif编辑

image.gif编辑

说完await,我们再来看看async

async来修饰一个方法,表明这个方法是异步的,声明的方法的返回类型必须为:voidTaskTask<TResult>。方法内部必须含有await修饰的方法,如果方法内部没有await关键字修饰的表达式,哪怕函数被async修饰也只能算作同步方法,执行的时候也是同步执行的。

因此await和async是形影不离的,如下创建两个方法

Task<string> ReadAsync()
    {
        return File.ReadAllTextAsync(@"D:\1.txt");
    }
    async Task<string> ReadAsync2()
    {
        return await File.ReadAllTextAsync(@"D:\1.txt");
    }

image.gif


目录
相关文章
|
7月前
|
C# 开发者
深入理解C#中的`Task<T>`:异步编程的核心
【1月更文挑战第3天】本文旨在探讨C#中`Task<T>`的使用和理解,作为异步编程模式的核心组件。`Task<T>`允许开发者在不阻塞主线程的情况下执行异步操作,并返回一个指定类型`T`的结果。通过定义返回`Task<T>`的异步方法、使用`async`和`await`关键字、处理异常以及获取任务结果,开发者可以编写出高效且响应迅速的应用程序。此外,本文还介绍了如何配置任务以及实现任务的连续性和组合,为掌握C#中的异步编程提供了全面的指导。
|
3月前
|
C# UED
C#一分钟浅谈:异步编程基础 (async/await)
在现代软件开发中,异步编程对于提升应用性能和响应性至关重要,尤其是在处理网络请求和文件读 异步编程允许程序在等待操作完成时继续执行其他任务,从而提高用户体验、高效利用资源,并增强并发性。在 C# 中,`async` 用于标记可能包含异步操作的方法,而 `await` 则用于等待异步操作完成。 示例代码展示了如何使用 `async` 和 `await` 下载文件而不阻塞调用线程。此外,本文还讨论了常见问题及解决方案,如不在 UI 线程上阻塞、避免同步上下文捕获以及正确处理异常。
53 0
|
C#
C#异步编程
C#异步编程
186 0
|
C#
C#网络应用编程,实验七: 异步编程练习
C#网络应用编程,实验七: 异步编程练习
121 1
C#网络应用编程,实验七: 异步编程练习
|
C#
C#网络应用编程,异步编程基础练习
C#网络应用编程,异步编程基础练习
149 1
C#网络应用编程,异步编程基础练习
|
SQL 开发框架 .NET
C#5.0-原生异步编程方式
微软提供的最新的异步编程基础设施。它允许我们以模块化的方式设计程序,来组合不同的异步操作。
117 0
C#5.0-原生异步编程方式
|
Java .NET C#
C#并发编程之异步编程(线程讨论)
C#并发编程之异步编程(线程讨论)写在前面本篇是异步编程系列的第三篇,本来计划第三篇的内容是介绍异步编程中常用的几个方法,但是前两篇写出来后,身边的朋友总是会有其他问题,所以决定在续写一篇,作为异步编程(一)和异步编程(二)的补充。
1458 0
|
C# 编译器 数据库
C#并发编程之异步编程(二)
C#并发编程之异步编程(二)写在前面前面一篇文章介绍了异步编程的基本内容,同时也简要说明了async和await的一些用法。本篇文章将对async和await这两个关键字进行深入探讨,研究其中的运行机制,实现编码效率与运行效率的提升。
1424 0
C#并发编程之异步编程(一)
C#并发编程之异步编程(一) 写在前面       C#5.0中,对异步编程进行了一次革命性的重构,引入了async和await这两个关键字,使得开发人员在不需要深刻了解异步编程的底层原理,就可以写出十分优美而又代码量极少的代码。
1409 0