【.NET】- async await 异步编程
为什么需要异步,异步对可能起阻止作用的活动(例如,应用程序访问 Web 时)至关重要。 对 Web 资源的访问有时很慢或会延迟。 如果此类活动在同步过程中受阻,则整个应用程序必须等待。 在异步过程中,应用程序可继续执行不依赖 Web 资源的其他工作,直至潜在阻止任务完成。
本节将一步一步带领大家理解async和await。
期间会有
Hello World,原理介绍,异步会提高程序的运行速度吗,async和await,MVC中的异步Action,以及线程中常涉及到的线程安全和信号量。
Hello World
static void Main(string[] args)
{
new Thread(Test) { IsBackground = false }.Start(); //.Net 在1.0的时候,就已经提供最基本的API.
ThreadPool.QueueUserWorkItem(o => Test()); //线程池中取空闲线程执行委托(方法)
Task.Run((Action)Test); //.Net 4.0以上可用
Console.WriteLine("Main Thread");
Console.ReadLine();
} static void Test()
{
Thread.Sleep();
Console.WriteLine("Hello World");
原理
其实不管是Task,ThreadPool,本质最终都是Thread。只不过微软帮我们在简化线程控制的复杂度。
线程池是CLR中事先定义好的一些线程。Task取的线程池,只不过在语法上,可以非常方便取返回值。
异步会提高程序的运行速度吗
多线程会提高程序的效率,不会提高运行速度。
这就好比这一个任务让前台花1个小时。前台完成10分钟的时候
打电话给经理,让他安排一个人来干30分钟(new Thread()),他干剩下的20分钟。(创建线程,需要时间,内存资源)
或者从旁边空闲的同事中(ThreadPool 或 Task),拉一个人过来干30分钟。他干剩下的20分钟。(需要的时间少,资源本来就存在)
从上看出,异步会让一份任务时间变长。资源消耗更多。但是可以让前台(UI线程)空闲下来,听从领导(用户)指挥。
async和await只是一个标记
首先看个Demo:
static void Main(string[] args)
{
Task.Run(() => //异步开始执行
{
Thread.Sleep(); //异步执行一些任务
Console.WriteLine("Hello World"); //异步执行完成标记
});
Thread.Sleep(); //主线程在执行一些任务
Console.WriteLine("Main Thread"); //主线程完成标记
Console.ReadLine();
}
执行结果:
这个很正常。但是我们希望先执行主线程完成标记,不改动主线程和Task的任务情况下,如何处理?
使用await和async:
static void Main(string[] args)
{
Say(); //由于Main不能使用async标记
Console.ReadLine();
}
private async static void Say()
{
var t = TestAsync();
Thread.Sleep(); //主线程在执行一些任务
Console.WriteLine("Main Thread"); //主线程完成标记
Console.WriteLine(await t); //await 主线程等待取异步返回结果
}
static async Task<string> TestAsync()
{
return await Task.Run(() =>
{
Thread.Sleep(); //异步执行一些任务
return "Hello World"; //异步执行完成标记
});
}
1.凡是使用await关键字的方法,都必须打上async标记。
2.async表示方法内有异步方法,调用async方法,会立刻另起线程执行。
3.await只是显示等待线程结束。await表示等待异步方法执行完,并取返回值。
MVC中的异步Action
既然多线程不能提高运行速度,而且每次请求Asp.net程序都是发起一个新的线程,为什么还要用多线程让其“降速”?
为了提高网站的吞吐量。
在MVC中,如果采用异步Action,则会像下面情况执行。
1.请求到达IIS,IIS应用程序池分配一个worker线程用来响应请求。
2.worker线程,执行异步操作,调用CLR线程池线程处理。
3.释放worker线程,响应其他请求。
4.异步操作执行完,w3wp(应用程序池进程)再次分配一个worker线程继续响应。
上述使用场景中,会获取两次worker 线程,这两次获取的线程可能相同,也可能会不同。如果有比较耗时的任务,非常建议把同步请求转换为异步。
线程安全和信号量
先举个线程不安全的例子。
static void Main(string[] args)
{
Task.Run((Action)Test);
Task.Run((Action)Test);
Console.ReadLine();
} private static void Test()
{
if (!IsComplete)
{
//todo other
Thread.Sleep();
Console.WriteLine("执行完成");
IsComplete = true;
}
} public static bool IsComplete { get; set; }
上面的执行结果,这就是线程不安全。(多线程访问同一段代码 产生不确定结果。)
如何解决,涉及到线程锁的概念。线程锁会让多线程访问的时候,一次只允许一个线程进入。
线程锁例子
private static readonly object lockObj = new object();
public static bool IsComplete { get; set; }
static void Main(string[] args)
{
Task.Run((Action)Test);
Task.Run((Action)Test);
Console.ReadLine();
} private static void Test()
{
lock (lockObj) //锁住的必须是引用类型。由于在静态方法中,则锁住静态引用类型。
{
if (!IsComplete)
{
//todo other
Thread.Sleep();
Console.WriteLine("执行完成");
IsComplete = true;
}
}
}
信号量
线程锁的技术使一块代码只能一个线程进入。信号量的存在,则是让同一块代码指定多个线程进入。
信号量(SemaphoreSlim)例子
static readonly SemaphoreSlim slim = new SemaphoreSlim();
static void Main(string[] args)
{
for (int i = ; i < ; i++)
{
ThreadPool.QueueUserWorkItem(Test, i);
}
Console.ReadLine();
} private async static void Test(object i)
{
Console.WriteLine("准备执行" + i);
await slim.WaitAsync();
Console.WriteLine("开始执行" + i);
//todo other
await Task.Delay();
Console.WriteLine("执行结束" + i);
slim.Release();
}
上面执行结果
【.NET】- async await 异步编程的更多相关文章
- 【转】C# Async/Await 异步编程中的最佳做法
Async/Await 异步编程中的最佳做法 Stephen Cleary 近日来,涌现了许多关于 Microsoft .NET Framework 4.5 中新增了对 async 和 await 支 ...
- .NET Web应用中为什么要使用async/await异步编程
前言 什么是async/await? await和async是.NET Framework4.5框架.C#5.0语法里面出现的技术,目的是用于简化异步编程模型. async和await的关系? asy ...
- C#中 Thread,Task,Async/Await 异步编程
什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务,调 ...
- async/await 异步编程(转载)
转载地址:http://www.cnblogs.com/teroy/p/4015461.html 前言 最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入 ...
- async/await 异步编程
前言 最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入的,由于之前对于异步编程不是很了解,所以花费了一些时间学习一下相关的知识,并整理成这篇博客,如果在 ...
- c# async/await异步编程死锁的问题
在异步编程中,如果稍有不注意,就会造成死锁问题.何为死锁:即两个以上的线程同时争夺被互相锁住的资源,两个都不放手. 在UI或asp.net中,容易造成死锁的代码如下所示: private void b ...
- c# 关于async/await异步编程的浅析和使用
线程的同步运行,时效性慢,异步运行,时效性快! 在c#5.0引出了async/await关键字,可以用其来进行异步编程. async/await定义异步方法的语法如下: 1.在方法的返回类型前面加上a ...
- .NET 中的 async/await 异步编程
原文出处: Teroy 的博客 前言 最近在学习Web Api框架的时候接触到了async/await,这个特性是.NET 4.5引入的,由于之前对于异步编程不是很了解,所以花费了一些时间学习一下相关 ...
- Async await 异步编程说明
希望在编程上有些许提高所以 最近连续2篇博客都在说明多线程和异步编程的使用,异步和多线程之间区别请自行百度,因为理解不是特别透彻就不在叙述以免误导大家,这里写下新研究整理 task 和 await ...
- ASP.Net中的async+await异步编程
在.NET Framework4.5框架.C#5.0语法中,通过async和await两个关键字,引入了一种新的基于任务的异步编程模型(TAP).在这种方式下,可以通过类似同步方式编写异步代码,极大简 ...
随机推荐
- 第1天 Java基础语法
Java基础语法 今日内容介绍 Java开发环境搭建 HelloWorld案例 注释.关键字.标识符 数据(数据类型.常量) Java开发环境搭建 Java概述 众所周知Java是一门编程语言,编程语 ...
- struts2学习笔记四
一.contextMap中的数据操作 root根:List 元素1 元素2 元素3 元素4 元素5 contextMap:Map key value application Map key value ...
- python--复习之路的目录
想要看时点链接看看,常来复习,温故而知新,可以为师矣. 1:基本类型 python--基本类型之字符串 python--基本类型之列表 python--基本类型之元组 python--基本类型之集合 ...
- 推荐 的FPGA设计经验(4) 时钟和寄存器控制架构特性使用
Use Clock and Register-Control Architectural Features FPGAs provide device-wide clocks and register ...
- WebService第二天——WebService框架CXF
一.CXF 1.什么是CXF Apache CXF = Celtix + XFire,开始叫 Apache CeltiXfire,后来更名为 Apache CXF 了,以下简称为 CXF.CXF 继承 ...
- Prism for WPF 搭建一个简单的模块化开发框架(三) 给TreeView加样式做成菜单
原文:Prism for WPF 搭建一个简单的模块化开发框架(三) 给TreeView加样式做成菜单 昨天晚上把TreeView的样式做了一下,今天给TreeView绑了数据,实现了切换页面功能 上 ...
- WPF 自定义ProgressBar滚动条样式
一.前言 滚动条一般用于加载进度,我们在看视频的时候或者在浏览网页的时候经常能看到加载进度的页面.在程序开发中,默认的进度加载样式可能跟程序风格不太一样,或者加载进度的时候需要更改一下加载的样式.这个 ...
- Mybatis之XML、注解
前言 上篇简单介绍了Mybatis的简单实用,本篇先对上次实验环境的一些内容进行优化,然后验证Mybatis的XML配置以及注解方式. 实验环境优化 数据库配置 在mybatis的配置文件中,引入数据 ...
- Docker介绍及安装
Docker介绍 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制, ...
- APP产品设计流程图
产品设计流程(toB) 工作有半个月了,遇到了很多问题,也在不断学习和充实自己,让自己的工作变得更加清晰和流程化,所以整理了这么个设计流程. 收集整理一切有用或则以后可能会用的文档. 从文档里面提炼用 ...