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-上锁;开锁必须由上锁的 ...
随机推荐
- C++命名空间、函数重载、缺省参数、内联函数、引用
一 .C++入门 1.C++关键字 2.命名空间 3.C++输入&输出 4.缺省参数 5.函数重载 6.引用 7.内联函数 8.auto关键字 9.基于范围的for循环 10.指针空值null ...
- 【原创】SSRS (SQL Serve Reporting Service) 访问权限的问题
问题:The permissions granted to user 'TOUCHPOINTMED\sshi' are insufficient for performing this operati ...
- SELECT列表中的标量子查询
发现了一种表连接新的写法,以前还没有这样写过或者见别人写过.跟同学聊天他们公司却很多人这样写,看来真的要学学sql了 表 CREATE TABLE `t_book` ( `FId` ) NOT NUL ...
- Form表单如何可以传递多个值传递List数组对象到后台的解决办法
举例说明: 后台有一个对象 User ,结构如下: 后台有一个对象 User ,结构如下: public class User{ private String username; private Li ...
- Android 开发工具类 31_WebService 获取手机号码归属地
AndroidInteractWithWebService.xml <?xml version="1.0" encoding="utf-8"?> & ...
- 关于class的签名Signature
举例1: public class Test05<A, B extends java.util.List<String>, C extends InputStream&Ser ...
- jquery插件开发的demo
(function ($) { $.fn.extend({ "highLight": function (options) { //检测用户传进来的参数是否合法 if (!isVa ...
- python笔记07-----打包模块(shutil,zipfile,tarfile)
1.shutil模块 复制删除 import shutil shutil.copy('filename', 'test2') # copy方法 f1 = open('filename',encodin ...
- Linux-(vmstat,iostat,netstat)
vmstat命令 vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写,可对操作系统的虚拟内存.进程.CPU活动进行监控.他是对系统的整体情况进行统计,不足之处是无 ...
- Innosetup的状态页面和向导页面解释
1.安装: CurStepChanged所对应的全部状态:3种 1.1. CurStep=ssInstall --是在程序实际安装前(所有配置都准备好了) 1.2. CurSt ...