为什么需要异步,异步对可能起阻止作用的活动(例如,应用程序访问 Web 时)至关重要。 对 Web 资源的访问有时很慢或会延迟。 如果此类活动在同步过程中受阻,则整个应用程序必须等待。 在异步过程中,应用程序可继续执行不依赖 Web 资源的其他工作,直至潜在阻止任务完成。

  本节将一步一步带领大家理解async和await。

  期间会有

  Hello World原理介绍异步会提高程序的运行速度吗async和awaitMVC中的异步Action,以及线程中常涉及到的线程安全信号量,以及微软提供的异步API

  推荐先看后顶,学的更快!

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(1000);
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(1000); //异步执行一些任务
Console.WriteLine("Hello World"); //异步执行完成标记
});
Thread.Sleep(1100); //主线程在执行一些任务
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(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 线程,这两次获取的线程可能相同,也可能会不同。如果有比较耗时的任务,非常建议把同步请求转换为异步。

线程安全和信号量

  先举个线程不安全的例子。

        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; }

  上面的执行结果,这就是线程不安全。(多线程访问同一段代码 产生不确定结果。)

  

如何解决,涉及到线程锁的概念。线程锁会让多线程访问的时候,一次只允许一个线程进入。

线程锁例子

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)例子

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 访问

HttpClientSyndicationClient

使用文件

StorageFileStreamWriterStreamReaderXmlReader

使用图像

MediaCaptureBitmapEncoderBitmapDecoder

WCF 编程

同步和异步操作

作者:Never、C

本文链接:http://www.cnblogs.com/neverc/p/4368821.html

[C#] 谈谈异步编程async await的更多相关文章

  1. 异步编程Async/await关键字

    异步编程Async \await 关键字在各编程语言中的发展(出现)纪实. 时间 语言版本 2012.08.15 C#5.0(VS2012) 2015.09.13 Python 3.5 2016.03 ...

  2. 抓住异步编程async/await语法糖的牛鼻子: SynchronizationContext

    长话短说,本文带大家抓住异步编程async/await语法糖的牛鼻子: SynchronizationContext 引言 C#异步编程语法糖async/await,使开发者很容易就能编写异步代码. ...

  3. 温故知新,CSharp遇见异步编程(Async/Await),聊聊异步编程最佳做法

    什么是异步编程(Async/Await) Async/Await本质上是通过编译器实现的语法糖,它让我们能够轻松的写出简洁.易懂.易维护的异步代码. Async/Await是C# 5引入的关键字,用以 ...

  4. javascript异步编程 Async/await

    Async/await Async/await 在学习他之前应当补充一定的 promise 知识 它是一种与 promise 相配合的特殊语法,目前被认为是异步编程的终级解决方案 值得我们每一个人学习 ...

  5. .net 异步编程async & await关键字的思考

    C# 5.0引入了两个关键字 async和await,这两个关键字在很大程度上帮助我们简化了异步编程的实现代码,而且TPL中的task与async和await有很大的关系 思考了一下异步编程中的asy ...

  6. 异步编程async/await

    什么是异步? 在异步程序中,程序代码不需要按照编写时的顺序严格执行,有时需要一在一个新的线程中运行一部分代码,有时无需创建新的 线程,但是为了更好的利用单个线程的能力,需要改变代码的执行顺序. 进程 ...

  7. c#异步编程async await

    可以代替协程了 但是需要.net4 版本 unity2017以上版本可以用了 再也可以不用蛋疼的没有返回值的协程了 //异步编程,和Task一起用 async void TestAsync(){ // ...

  8. .NetCore 异步编程 - async/await

    前言: 这段时间开始用.netcore做公司项目,发现前辈搭的框架通篇运用了异步编程方式,也就是async/await方式,作为一个刚接触的小白,自然不太明白其中原理,最重要的是,这个玩意如果不明白基 ...

  9. .net 温故知新:【5】异步编程 async await

    1.异步编程 异步编程是一项关键技术,可以直接处理多个核心上的阻塞 I/O 和并发操作. 通过 C#.Visual Basic 和 F# 中易于使用的语言级异步编程模型,.NET 可为应用和服务提供使 ...

随机推荐

  1. MVC使用基架添加控制器出现的错误:无法检索XXX的元数据

    环境 vs2012 框架 mvc3 数据库  sqlservercompact4.0 出现的错误如下: “ ---------------------------Microsoft Visual St ...

  2. 【css】a:hover 设置上下边框在 ie6 和 ie7 下失效

    前段时间在写样式的时候发现了这个问题,虽然当时就解决了这个 bug 不过还是记录下,以免再次出现这样的问题. demo 代码: <!doctype html> <html lang= ...

  3. 阿里云里面的Linux 系统挂载数据盘

    转自:http://www.cnblogs.com/adjk/p/5112360.html 适用系统:非IO优化+SSD云盘Linux(Redhat , CentOS,Debian,Ubuntu)实例 ...

  4. 分享一个web应用程序池管理工具

    因为项目在联调阶段由于各种各样的原因需要重启应用程序池,而调试服务器基本都需要远登操作.同样的情况也会发生在线上,如果公司权限控制得比较严格,每次都要多部门的服务器权限申请的话有点麻烦, 所以抽点时间 ...

  5. Oracle-ARCGIS-SDE 数据整合遇到的问题

    一. 近日在做全文检索,基础采用oracle text,版本是10g,做好管理页面后,有功能是删除索引,就是生成drop index的语句.没有想到这个全文检索的index这么直接弄还不行,经过这样删 ...

  6. [原创]Android系统中常用JAVA类源码浅析之HashMap

    由于是浅析,所以我只分析常用的接口,注意是Android系统中的JAVA类,可能和JDK的源码有区别. 首先从构造函数开始, /** * Min capacity (other than zero) ...

  7. Android JNI框架图

  8. [转]优秀Python学习资源收集汇总

    Python是一种面向对象.直译式计算机程序设计语言.它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用縮进来定义语句块.与Scheme.Ruby.Perl ...

  9. 写给已有编程经验的 Python 初学者的总结

    当我开始学习Python的时候,有些事我希望我一早就知道.我花费了很多时间才学会这些东西.我想要把这些重点都编纂到一篇文章当中.这篇文章的目标读者,是刚刚开始学习Python语言的有经验的程序员,想要 ...

  10. 使用GROUP BY统计记录条数 COUNT(*) DISTINCT

    例如这样一个表,我想统计email和passwords都不相同的记录的条数 CREATE TABLE IF NOT EXISTS `test_users` ( `email_id` ) unsigne ...