C#笔记14 异步编程Async,await,task类
前文
昨天碰到Mutex的遗弃问题,让初学者十分头痛啊,今天重整旗鼓来学异步编程,互联网学替了属于是。可以去看看前面的文章,如果可以,求个关注。
线程的基础用法: | C#笔记8 线程是什么?多线程怎么实现和操作?-CSDN博客 |
线程的创建和启动: | C#笔记9 对线程Thread的万字解读 小小多线程直接拿下!-CSDN博客 |
线程的阻止和中止: | C#笔记10 Thread类怎么终止(Abort)和阻止(Join)线程-CSDN博客 |
线程的属性: | C#笔记11 获取线程及其信息,什么是优先级、单元状态、线程状态、执行状态、线程名称以及其他属性?-CSDN博客 |
线程的方法: | C#笔记12 线程的常见方法 中断,取消终止,旋转等待,读写字段,分配数据槽-CSDN博客 |
同步线程: | C#笔记13 线程同步概念及其实现,详解lock,Monitor,Mutex代码用法-CSDN博客 |
Mutex遗弃问题: | 问题:如何安全的使用Mutex(防遗弃), AbandonedMutexException:The wait completed due to an abandoned mutex.-CSDN博客 |
概念
什么是异步编程?
我们说过,当我们实现了多线程,我们就拥有了分别执行多个代码块的能力,如果他们执行各自的逻辑,互相不存在等待和阻塞的话,就是完全的异步,但是我们往往会遇到多个线程同时访问或者请求同一个资源的情况下,如果任由他们执行,明显可能会导致数据的错误和资源的抢占,那么为我们就使用了同步的方法来控制线程之间的协作。
异步编程就是又回到了之前的问题,我们知道我们线程本身是异步的,但是由于共享资源和共享代码等需要同步机制,所以进行等待。但是在异步编程中,某些操作(通常是I/O密集型操作)可以在后台进行,而程序的其他部分可以继续运行。异步操作通常通过回调函数、事件、或任务来实现。
意思就是:有些时候虽然我们有一些必须要等待资源才能执行的操作,但是我们其实还有一部分事情是可以接着做的。没必要这个线程都卡在这个资源上。
实现方式
async,await关键字
在不同的编程语言中,这两个关键字起到的作用不同,我们仅以C#为样本理解。
async用于声明异步方法,await则用于调用异步方法。async方法执行遇到await时会立刻转移控制权给async方法的调用者。
调用者决定是否等待这个async方法执行完。
await会挂起当前方法,即阻塞这个方法向下执行,转交控制权给调用者。
一个方法中含有await,必须被声明为async方法。
调用泛型方法时,通常在方法前加上async关键字,这样方法调用的返回值就是泛型指定的T类型的值。
Task类
此类用于表示一个异步操作,对于有返回值的操作需要使用:Task<TResult>类。
属性及其说明:
AsyncState
获取创建 Task 时提供的状态对象;如果未提供,则为 null。
CompletedTask
获取已成功完成的任务。
CreationOptions
获取用于创建此任务的 TaskCreationOptions。
CurrentId
返回当前正在执行的 Task的 ID。
Exception
获取导致 Task 过早结束的 AggregateException。 如果 Task 成功完成或尚未引发任何异常,则返回 null。
Factory
提供对工厂方法的访问权限,用于创建和配置 Task 和 Task<TResult> 实例。
Id
获取此 Task 实例的 ID。
IsCanceled
获取此 Task 实例是否已完成执行,因为已取消。
IsCompleted
获取一个值,该值指示任务是否已完成。
IsCompletedSuccessfully
获取任务是否运行到完成。
IsFaulted
获取 Task 是否因未经处理的异常而完成。
Status
获取此任务的 TaskStatus。
用法
异步方法的声明与调用
方法如果使用async修饰,它就是一个异步方法。
特点:
方法名以Async结尾
返回值一般为Task<T>,其中T为真正的返回值。
如果没有返回值,建议把返回值声明为非泛型的task。
例子:
使用异步方法获取指定网页内容
async Task<string> DownloadAsync(string url)
{
using HttpClient httpc=new HttpClient();
string content = await httpc.GetStringAsync(url);
return content;
}
获取网页内容示例2:
async Task<string> DownloadAsync2(string url)
{
using HttpClient httpc = new HttpClient();
string content = await httpc.GetStringAsync(url);
await File.WriteAllTextAsync("baidu.html", content);
string s=await File.ReadAllTextAsync("baidu.html");
return s;
}
查看生成的文件:
网页打开如图所示。
注意,调用异步方法一定要使用await方法,否则会作为同步方法调用。
await关键字还有一个作用,可以把数据从我们的异步方法task<T>提取出来。不使用await的关键字的情况如下图所示:
下载网页的代码:
string c1= await DownloadAsync("https://www.baidu.com");
string c2= await DownloadAsync2("https://www.baidu.com");
Console.WriteLine(c1);
Console.WriteLine();
Console.WriteLine(c2);
async Task<string> DownloadAsync(string url)
{
using HttpClient httpc = new HttpClient();
string content = await httpc.GetStringAsync(url);
return content;
}
async Task<string> DownloadAsync2(string url)
{
using HttpClient httpc = new HttpClient();
string content = await httpc.GetStringAsync(url);
await File.WriteAllTextAsync("baidu.html", content);
string s=await File.ReadAllTextAsync("baidu.html");
return s;
}
多线程在winform中控制图形运动的代码。
Winform控制窗体中的控件自由移动代码-CSDN博客