c# 异步和同步问题(转载)
[C#] 谈谈异步编程async await
为什么需要异步,异步对可能起阻止作用的活动(例如,应用程序访问 Web 时)至关重要。 对 Web 资源的访问有时很慢或会延迟。 如果此类活动在同步过程中受阻,则整个应用程序必须等待。 在异步过程中,应用程序可继续执行不依赖 Web 资源的其他工作,直至潜在阻止任务完成。
本节将一步一步带领大家理解async和await。
期间会有
Hello World,原理介绍,异步会提高程序的运行速度吗,async和await,MVC中的异步Action,以及线程中常涉及到的线程安全和信号量,以及微软提供的异步API
推荐先看后顶,学的更快!
Hello World

|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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(1000); Console.WriteLine("Hello World");} |
原理
其实不管是Task,ThreadPool,本质最终都是Thread。只不过微软帮我们在简化线程控制的复杂度。
线程池是CLR中事先定义好的一些线程。Task取的线程池,只不过在语法上,可以非常方便取返回值。
异步会提高程序的运行速度吗
多线程会提高程序的效率,不会提高运行速度。
这就好比这一个任务让前台花1个小时。前台完成10分钟的时候
打电话给经理,让他安排一个人来干30分钟(new Thread()),他干剩下的20分钟。(创建线程,需要时间,内存资源)
或者从旁边空闲的同事中(ThreadPool 或 Task),拉一个人过来干30分钟。他干剩下的20分钟。(需要的时间少,资源本来就存在)
从上看出,异步会让一份任务时间变长。资源消耗更多。但是可以让前台(UI线程)空闲下来,听从领导(用户)指挥。
async和await只是一个标记
首先看个Demo,
|
1
2
3
4
5
6
7
8
9
10
11
|
static void Main(string[] args){ Task.Run(() => //异步开始执行 { Thread.Sleep(1000); //异步执行一些任务 Console.WriteLine("Hello World"); //异步执行完成标记 }); Thread.Sleep(1100); //主线程在执行一些任务 Console.WriteLine("Main Thread"); //主线程完成标记 Console.ReadLine();} |
发现执行结果是:

这个很正常。但是我们希望先执行主线程完成标记,不改动主线程和Task的任务情况下,如何处理?
使用await和async
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
static void Main(string[] args){ Say(); //由于Main不能使用async标记 Console.ReadLine();}private async static void Say(){ var t = TestAsync(); Thread.Sleep(1100); //主线程在执行一些任务 Console.WriteLine("Main Thread"); //主线程完成标记 Console.WriteLine(await t); //await 主线程等待取异步返回结果}static async Task<string> TestAsync(){ return await Task.Run(() => { Thread.Sleep(1000); //异步执行一些任务 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 线程,这两次获取的线程可能相同,也可能会不同。如果有比较耗时的任务,非常建议把同步请求转换为异步。
线程安全和信号量
先举个线程不安全的例子。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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(500); Console.WriteLine("执行完成"); IsComplete = true; }}public static bool IsComplete { get; set; } |
上面的执行结果,这就是线程不安全。(多线程访问同一段代码 产生不确定结果。)

如何解决,涉及到线程锁的概念。线程锁会让多线程访问的时候,一次只允许一个线程进入。
线程锁例子
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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(500); Console.WriteLine("执行完成"); IsComplete = true; } } } |
信号量
线程锁的技术使一块代码只能一个线程进入。信号量的存在,则是让同一块代码指定多个线程进入。
信号量(SemaphoreSlim)例子
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
static readonly SemaphoreSlim slim = new SemaphoreSlim(2); static void Main(string[] args) { for (int i = 0; i < 5; 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(1000); Console.WriteLine("执行结束" + i); slim.Release(); } |
上面执行结果

从 .NET Framework 4.5 和 Windows 运行时中列出的 API 包含支持异步编程的方法。
|
应用程序区域 |
包含异步方法的受支持的 API |
|---|---|
|
Web 访问 |
|
|
使用文件 |
|
|
使用图像 |
|
|
WCF 编程 |
作者:Never、C
本文链接:http://www.cnblogs.com/neverc/p/4368821.html
c# 异步和同步问题(转载)的更多相关文章
- 简单的node爬虫练手,循环中的异步转同步
简单的node爬虫练手,循环中的异步转同步 转载:https://blog.csdn.net/qq_24504525/article/details/77856989 看到网上一些基于node做的爬虫 ...
- win10 uwp 异步转同步
原文:win10 uwp 异步转同步 有很多方法都是异步,那么如何从异步转到同步? 可以使用的方法需要获得是否有返回值,返回值是否需要. 如果需要返回值,使用GetResults 如从文件夹获取文件: ...
- [转帖]再谈IO的异步,同步,阻塞和非阻塞
再谈IO的异步,同步,阻塞和非阻塞 https://yq.aliyun.com/articles/53674?spm=a2c4e.11155435.0.0.48bfe8efHUE8wg krypt ...
- ASP.NET sync over async(异步中同步,什么鬼?)
async/await 是我们在 ASP.NET 应用程序中,写异步代码最常用的两个关键字,使用它俩,我们不需要考虑太多背后的东西,比如异步的原理等等,如果你的 ASP.NET 应用程序是异步到底的, ...
- 入门级的按键驱动——按键驱动笔记之poll机制-异步通知-同步互斥阻塞-定时器防抖
文章对应视频的第12课,第5.6.7.8节. 在这之前还有查询方式的驱动编写,中断方式的驱动编写,这篇文章中暂时没有这些类容.但这篇文章是以这些为基础写的,前面的内容有空补上. 按键驱动——按下按键, ...
- C#中的异步和同步
同步 同步(英语:Synchronization [ˌsɪŋkrənaɪ'zeɪʃn]),指对在一个系统中所发生的事件(event)之间进行协调,在时间上出现一致性与统一化的现象.说白了就是多个任务一 ...
- 漫话JavaScript与异步·第三话——Generator:化异步为同步
一.Promise并非完美 我在上一话中介绍了Promise,这种模式增强了事件订阅机制,很好地解决了控制反转带来的信任问题.硬编码回调执行顺序造成的"回调金字塔"问题,无疑大大提 ...
- C# 异步转同步
当我们的程序运行时,调用了一段异步的逻辑A,这段异步的逻辑无法转化为同步(如动画.下载进度等) 而,我们又需要等待异步逻辑A处理完成,然后再执行其它逻辑B. 那就迫切需要将异步转同步了! //参数bo ...
- nodejs异步转同步
项目在微信环境开发,需要获取access_token进行授权登录和获取用户信息. 特意把这块功能拿出来封装一个自定义module module.exports = new Wechat(con.app ...
- Linux 多线程 - 线程异步与同步机制
Linux 多线程 - 线程异步与同步机制 I. 同步机制 线程间的同步机制主要包括三个: 互斥锁:以排他的方式,防止共享资源被并发访问:互斥锁为二元变量, 状态为0-开锁.1-上锁;开锁必须由上锁的 ...
随机推荐
- LeetCode题解-147 对链表进行插入排序 Medium
对链表进行插入排序. 插入排序的动画演示如上.从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示). 每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中. 插 ...
- chrome断点调试&&其他技巧
chrome断点调试 1. 在编写JavaScript代码时,如果 出现了bug,就要不断的去找错误,如果console控制台中提示还好说,可是没有提示恐怕就要费一番周折了.但是有了chrome这个浏 ...
- java8时间类
java8引入了一套全新的时间日期API 新的时间及日期API位于java.time中java.time包中的是类是不可变且线程安全的. 下面是一些关键类 LocalDateTime // ...
- Android 开发工具类 17_setAlarm
Alarm 是在应用程序生命周期之外设置的,所以它们十分适合于调度定时更新或者数据查询,从而避免了在后台持续运行 Service.但触发 Alarm 时,就会广播指定的 Pending Intent. ...
- 全连接层(FC)与全局平均池化层(GAP)
在卷积神经网络的最后,往往会出现一两层全连接层,全连接一般会把卷积输出的二维特征图转化成一维的一个向量,全连接层的每一个节点都与上一层每个节点连接,是把前一层的输出特征都综合起来,所以该层的权值参数是 ...
- GBDT多分类示例
相当于每次都是用2分类,然后不停的训练,最后把所有的弱分类器来进行汇总 样本编号 花萼长度(cm) 花萼宽度(cm) 花瓣长度(cm) 花瓣宽度 花的种类 1 5.1 3.5 1.4 0.2 山鸢尾 ...
- (转)linux内核调优参数对比和解释
[net] ######################## cat /proc/sys/net/ipv4/tcp_syncookies # 默认值:1 # 作用:是否打开SYN Cookie功能,该 ...
- boost bind使用指南
bind - boost 头文件: boost/bind.hpp bind 是一组重载的函数模板.用来向一个函数(或函数对象)绑定某些参数. bind的返回值是一个函数对象. 它的源文件太长了. 看不 ...
- jquery完全版下载
查看演示立刻下载错误提交填加用法 jquery-2.1.1 (注!jquery-2.0以上版本不再支持IE 6/7/8) 百度引用地址 (推荐目前最稳定的,不会出现延时打不开情况) 百度压缩版引用 ...
- springMVC中ModelAndView学写笔记
api介绍: 构造函数摘要 ModelAndView() bean样式用法的默认构造函数:填充bean属性,而不是传递构造函数参数. ModelAndView(Object vie ...