为什么需要异步,异步对可能起阻止作用的活动(例如,应用程序访问 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. Android系列---JSON数据解析

    您可以通过点击 右下角 的按钮 来对文章内容作出评价, 也可以通过左下方的 关注按钮 来关注我的博客的最新动态. 如果文章内容对您有帮助, 不要忘记点击右下角的 推荐按钮 来支持一下哦 如果您对文章内 ...

  2. IOS越狱开发之——进程通讯

    Mac OS下的IPC方式种类很多,大约有下面几种. 1. Mach API 2. CFMessagePort 3. Distributed Objects (DO) 4. Apple events  ...

  3. IIS服务器下做301永久重定向设置方法

    实现方法如下: 1.新建一个站点,对应目录如E:\wwwroot\301web.该目录下只需要1个文件,即index.html或者加个404.htm.绑定要跳转的域名,如图: 2.在IIS中选中刚才我 ...

  4. 【html】button按钮的一些问题

    问题: button 按钮在不设置 type 属性时,在不同的浏览器作用不一样.举个例子: html: <!doctype html> <html lang="en&quo ...

  5. LeetCode: Convert Sorted List to Binary Search Tree 解题报告

    Convert Sorted List to Binary Search Tree Given a singly linked list where elements are sorted in as ...

  6. iOS AVKit音视频播放全面详解

    公司项目中经常要用到音视频处理,也需要去定制一些东西,然后整理这些音视频处理就显得尤为重要!方便自己和广大朋友学习收藏! 以下参考连接特别重要: 苹果官方:AVKit API 苹果官方:AVFound ...

  7. CSS基础(二):基础和语法

    CSS语法 CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明.选择器通常是您需要改变样式的 HTML 元素. selector {declaration1; declaration2; . ...

  8. php网页切图/js切图

    PhantomJS抓取网站页面信息以及网站截图 http://phantomjs.org/download.html PHP imagegrabscreen和imagegrabwindow(截取网站缩 ...

  9. 对象与Byte数组相互转化工具方法

    /** * 对象转byte * @param obj * @return */ private byte[] ObjectToByte(Object obj) { byte[] bytes = nul ...

  10. Java知多少(111)数据库之修改记录

    修改数据表记录也有3种方案. 一.使用Statement对象 实现修改数据表记录的SQL语句的语法是:    update表名 set 字段名1 = 字段值1,字段名2 = 字段值2,……where特 ...