前言

本节主要介绍异步编程中Task、Async和Await的基础知识。
什么是异步?
异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程。
异步和多线程
相同点:避免调用线程阻塞,从而提高软件的可响应性。
不同点:
异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能。C#5.0 .NET4.5 以后关键字Async和Await的使用,使得异步编程变得异常简单。
多线程中的处理程序依然是顺序执行,但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。
异步应用场景及原理
异步主要应用于IO操作,数据库访问,磁盘操作,Socket访问、HTTP/TCP网络通信
原因:对于IO操作并不需要CPU进行过多的计算,这些数据主要通过磁盘进行处理,如果进行同步通信无法结束,需要创建更多的线程资源,线程的数据上下文频繁的切换也是对资源的浪费,针对IO操作不需要单独的分配一个线程来处理。
举例说明:
操作:服务器接收HTTP请求对数据库进行操作然后返回
同步处理请求的线程会被阻塞,异步处理请求的线程不会阻塞。
任务
在使用任务之前,针对线程的调用大多都用线程池提供的静态方法QueueUserWorkItem,但是这个函数有很多的限制,其中最大的问题就是没有内部机制可以让开发者知道操作在什么时候完成,也没有机制在操作完成时获取返回值,微软为了解决这个问题引入了任务的概念。
首先构造一个Task<TResult>对象,并为TResult传递返回值,开始任务之后等待它并回去结果,示例代码:
static void Main(string[] args)
{
Console.WriteLine("开始进行计算");
// ThreadPool.QueueUserWorkItem(Sum, 10);
Task<int> task = new Task<int>(Sum, 100);
task.Start();
//显示等待获取结果
task.Wait();
//调用Result时,等待返回结果
Console.WriteLine("程序结果为 Sum = {0}",task.Result);
Console.WriteLine("程序结束");
Console.ReadLine();
}
public static int Sum(object i)
{
var sum = 0;
for (var j = 0; j <= (int) i; j++)
{
Console.Write("{0} + ",sum);
sum += j;
}
Console.WriteLine( " = {0}",sum);
return sum;
}
除了wait等待单个任务外,task还提供了等待多个任务,WaitAny和WaitAll,它阻止调用线程,直到数组中所有的Task对象完成。
取消任务
任务的取消同样使用的是.NET Framework的标准取消操作模式,首先需要创建一个CancellationTokenSource对象,然后在函数中加入参数CancellationToken,将CancellationTokenSource的Token传递给方法,然后调用IsCancellationRequested获取是否已经取消该值进行判断。
static void Main(string[] args)
{
Console.WriteLine("开始进行计算");
// ThreadPool.QueueUserWorkItem(Sum, 10);
var ctx = new CancellationTokenSource();
var task = new Task<int>(() => Sum(ctx.Token, 100000));
task.Start();
//显示等待获取结果
//task.Wait(ctx.Token);
Thread.Sleep(1000);
ctx.Cancel();
//调用Result时,等待返回结果
Console.WriteLine("程序结果为 Sum = {0}", task.Result);
Console.WriteLine("程序结束");
Console.ReadLine();
}
public static int Sum(CancellationToken cts, object i)
{
var sum = 0;
for (var j = 0; j <= (int)i; j++)
{
if (cts.IsCancellationRequested) return sum;
Thread.Sleep(50);
Console.Write("{0} + ", sum);
sum += j;
}
Console.WriteLine(" = {0}", sum);
return sum;
}
任务完成后自动启动新任务
实际的开发应用中,经常出现一次任务完成后立刻启动另外一个任务,并且不能够使线程阻塞,在任务尚未完成时调用result会使程序阻塞,无法查看任务的执行进度,TASK提供了一个方法ContinueWith,它不会阻塞任何线程,当第一个任务完成时,会立即启动第二个任务。
static void Main(string[] args)
{
Console.WriteLine("开始进行计算");
// ThreadPool.QueueUserWorkItem(Sum, 10);
var ctx = new CancellationTokenSource();
var task = new Task<int>(() => Sum(ctx.Token, 100000));
task.Start();
var cwt = task.ContinueWith(p =>
{
Console.WriteLine("task result ={0} ",task.Result);
});
//显示等待获取结果
//task.Wait(ctx.Token);
Thread.Sleep(1000);
ctx.Cancel();
//调用Result时,等待返回结果
Console.WriteLine("程序结果为 Sum = {0}", task.Result);
Console.WriteLine("程序结束");
Console.ReadLine();
}
public static int Sum(CancellationToken cts, object i)
{
var sum = 0;
for (var j = 0; j <= (int)i; j++)
{
if (cts.IsCancellationRequested) return sum;
Thread.Sleep(50);
Console.Write("{0} + ", sum);
sum += j;
}
Console.WriteLine(" = {0}", sum);
return sum;
}
Async&Await 简单使用
使用Async&Await的主要目的是方便进行异步操作,因为.net 4.0 以前进行异步操作时比较复杂的,主要是通过调用微软提供的异步回调方法进行编程,如果遇到需要自己实现的方法显得非常头疼,.net的各个版本都有自己主推的技术,像.NET1.1中的委托,.NET2.0中的泛型,.NET3.0中的Linq,.NET4.0中的Dynimac,.net4.5主推的就是异步编程,大家只需要了解TASK+异步函数就可以实现异步编程。
async:告诉CLR这是一个异步函数。
await:将Task<TResult>返回值的函数进行异步处理。
示例目的:获取网址JS代码,并在界面显示。
private static async Task<string> DownloadStringWithRetries(string uri)
{
using (var client = new HttpClient())
{
// 第1 次重试前等1 秒,第2 次等2 秒,第3 次等4 秒。
var nextDelay = TimeSpan.FromSeconds(1);
for (int i = 0; i != 3; ++i)
{
try
{
return await client.GetStringAsync(uri);
}
catch
{
}
await Task.Delay(nextDelay);
nextDelay = nextDelay + nextDelay;
}
// 最后重试一次,以便让调用者知道出错信息。
return await client.GetStringAsync(uri);
}
}
static void Main(string[] args)
{
Console.WriteLine("获取百度数据");
ExecuteAsync();
Console.WriteLine("线程结束");
Console.ReadLine();
}
public static async void ExecuteAsync()
{
string text = await DownloadStringWithRetries("http://wwww.baidu.com");
Console.WriteLine(text);
}
运行结果发现,首先获取百度数据,线程结束,最后显示HTML代码,这是因为异步开启了新的线程,并不会造成线程阻塞。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
# C#
# 异步编程
# C# 委托的三种调用示例(同步调用 异步调用 异步回调)
# C#异步调用的好处和方法分享
# C#中异步回调函数用法实例
# C#异步编程ConfigureAwait的使用小结
# 死锁
# 回调
# 多线程
# 返回值
# 微软
# 重试
# 的是
# 主推
# 完成后
# 第一个
# 多个
# 也没
# 不需要
# 有很多
# 什么时候
# 并在
# 这是一个
# 第二个
# 只需要
# 会使
相关文章:
存储型VPS适合搭建中小型网站吗?
美食网站链接制作教程视频,哪个教做美食的网站比较专业点?
如何在建站之星网店版论坛获取技术支持?
湖北网站制作公司有哪些,湖北清能集团官网?
公司网站制作需要多少钱,找人做公司网站需要多少钱?
如何在Ubuntu系统下快速搭建WordPress个人网站?
建站之星后台管理:高效配置与模板优化提升用户体验
如何在建站之星绑定自定义域名?
建站主机选哪种环境更利于SEO优化?
东莞专业网站制作公司有哪些,东莞招聘网站哪个好?
公司网站设计制作厂家,怎么创建自己的一个网站?
定制建站流程步骤详解:一站式方案设计与开发指南
移民网站制作流程,怎么看加拿大移民官网?
建站之星Pro快速搭建教程:模板选择与功能配置指南
深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?
微网站制作教程,我微信里的网站怎么才能复制到浏览器里?
如何做静态网页,sublimetext3.0制作静态网页?
网站制作难吗安全吗,做一个网站需要多久时间?
深圳网站制作案例,网页的相关名词有哪些?
如何零成本快速生成个人自助网站?
PHP 500报错的快速解决方法
网站制作的软件有哪些,制作微信公众号除了秀米还有哪些比较好用的平台?
高防服务器:AI智能防御DDoS攻击与数据安全保障
合肥做个网站多少钱,合肥本地有没有比较靠谱的交友平台?
如何通过IIS搭建网站并配置访问权限?
建站主机与虚拟主机有何区别?如何选择最优方案?
如何在IIS中新建站点并配置端口与IP地址?
实惠建站价格推荐:2025年高性价比自助建站套餐解析
定制建站价位费用解析与套餐推荐全攻略
已有域名和空间如何快速搭建网站?
c# 在高并发下使用反射发射(Reflection.Emit)的性能
品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?
建站三合一如何选?哪家性价比更高?
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
建站168自助建站系统:快速模板定制与SEO优化指南
如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南
建站之星安装需要哪些步骤及注意事项?
建站之星安装失败:服务器环境不兼容?
济南网站制作的价格,历城一职专官方网站?
如何用腾讯建站主机快速创建免费网站?
韩国服务器如何优化跨境访问实现高效连接?
广东企业建站网站优化与SEO营销核心策略指南
如何在VPS电脑上快速搭建网站?
如何在阿里云ECS服务器部署织梦CMS网站?
建站之星安装后如何配置SEO及设计样式?
建站之星图片链接生成指南:自助建站与智能设计教程
免费制作小说封面的网站有哪些,怎么接网站批量的封面单?
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
制作门户网站的参考文献在哪,小说网站怎么建立?
微信小程序 五星评分(包括半颗星评分)实例代码
*请认真填写需求信息,我们会在24小时内与您取得联系。