接上文 多线程编程学习笔记——任务并行库(一)

接上文 多线程编程学习笔记——任务并行库(二)

接上文 多线程编程学习笔记——任务并行库(三)

接上文 多线程编程学习笔记——任务并行库(四)

通过前面的文章,已经学习了怎么使用线程,怎么使用线程同步,怎么使用线程池,怎么使用任务并行库。尽管通过上面的学习,对于线程的使用越来越简单。有没有更简单的方法呢。

C# 5.0之后,微软在c#语言中添加了两个关键字async与await,这是在TPL上面的更高一级的抽象,真正简化了异步编程的编程方式,从而有助于我们编写出真正健壮少bug的异步应用程序。下面我先来看一个最简单的示例。

async Task<string> AsyncHello()
{ await Task.Delay(TimeSpan.FromSeconds());
Return “ Hello world”;
}

使用async标记异步函数,建议返回async Task<T>。

Await只能使用在有async标志的方法内部。在async标记的方法内部最少要有一个await,当然,如果一个也没有,编译也不会报错,但是会有编译警告。如下图。

上面的代码在执行完await调用的代码之行后该方法会直接返回。如果同步执行,执行线程会阻塞2秒之后返回结果,本示例里在执行完await操作后,立即将工作线程放回线程池中,我们会异步等待。2秒后,我们会从线程池中取得工作线程并继续运行其中剩余的异步方法。这就允许我们在等待的2秒的时间里可以重用线程池中的线程,这对提高应用程序的可伸缩性非常重要。通过使用async与await我们拥有了线性的程序控制流程,但是执行过程却是异步的。

一、   使用await获取异步操作结果

本示例是学习await如何获取异步操作结果。同时会与TPL进行比较。

1.示例代码如下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading; namespace ThreadAsyncDemo
{ class Program
{
static void Main(string[] args)
{ Task t = AsyncWithTPL();
t.Wait();
t = AsyncWithAwait();
t.Wait();
Console.Read();
} static Task AsyncWithTPL()
{
Task<string> task1 = GetInfoAsync("Task 1"); Task task2 = task1.ContinueWith(task =>
Console.WriteLine(task1.Result), TaskContinuationOptions.NotOnFaulted);
Task task3 = task1.ContinueWith(task =>
Console.WriteLine(task1.Exception.InnerException), TaskContinuationOptions.OnlyOnFaulted);
return Task.WhenAny(task2, task1); } async static Task AsyncWithAwait()
{
try
{
string result = await GetInfoAsync("Task 4");
Console.WriteLine(result);
} catch (Exception ex)
{
Console.WriteLine(ex.Message); }
} async static Task<string> GetInfoAsync(string name)
{ await Task.Delay(TimeSpan.FromSeconds());
//throw new Exception("抛出异常信息!"); return string.Format(" Task {0} 正在运行在线程 ID={1}上。这个工作线程是否是线程池中的线程:{2}", name,
Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); }
}
}

2.程序运行的结果如下图。

程序同时运行了两个异步操作。其中一个是标准的TPL代码,另一个使用了async与await两个关键字。AsyncWithTPL启动了一个任务,运行两秒之后返回关于工作线程信息的字符串。然后我们定义了一个后续操作,用于在异步操作完成后打印出操作结果,还有另一个后续操作,用于万一有错误时,打印出异常信息。最终返回了一个代表其中一个后续操作任务的任务,并等等其在主函数中完成。

在asyncWithAwait方法中,我们对任务使用await并得到了相同 的结果。这和编写普通的同步代码的风格一样,即我们获取了任务的结果,打印了出来,如果任务完成时带有错误则捕获异常。关键不同的是这实际上是一个异步操作。使用await后,c#立即创建了一个任务,其中一个有后续操作任务,包含了await操作符后面的所有剩余代码。这个新任务也处理了异常。然后这个任务返回 到主方法并等待共完成 。

因此可以看出程序中的两段代码在概念上是相同的,使用await由编译 器隐式地处理了异步代码。

3. 我们把上面注释的抛出异常的代码,取消注释,然后运行程序。得到如下图的结果。

注:在gui与asp.net之类的环境 中不推荐 使用task.wait和taskResult方法同,因为如果代码写的不好,很容易导致死锁。

二、   在Lambda表达式中使用await操作符

本示例学习如何在lambda表达式中使用await。将学习如何编写一个使用了await的匿名方法,并且获取异步执行该方法的结果。

1.示例代码如下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading; namespace ThreadAsyncDemo
{ class Program
{ static void Main(string[] args)
{ Task t = AsyncProcess();
t.Wait();
Console.Read();
} async static Task AsyncProcess()
{ Func<String, Task<string>> asyncLambda = async name =>
{ await Task.Delay(TimeSpan.FromSeconds());
return string.Format(" Task {0} 正在运行在线程 ID={1}上。这个工作线程是线程池的线程:{2}" ,name,
Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
}; string result = await asyncLambda("async lambda");
Console.WriteLine(result); } } }

2.程序运行结果,如下图。

首先不能在main方法中使用async,我们将异步函数移到了asyncProcess中,然后使用async关键字声明了一个lambda表达式。由于 任何lambda表达式的类型都不能通过lambda自身来推断,所以不得不显示地指定类型为一字符串,并返回一个Task<string>对象 。

然后,我们定义 了lambda表达式体,这个方法虽然定义返回的是一个Task<string>对象 ,但实际上返回的是字符串,却没有编译错误。这是因为c#编译器自动 产生了一个任务并返回给我们。

最后一步就是打印出lambda 表达式执行后的结果。

多线程编程学习笔记——async和await(一)的更多相关文章

  1. 多线程编程学习笔记——async和await(二)

    接上文 多线程编程学习笔记——async和await(一) 三.   对连续的异步任务使用await操作符 本示例学习如何阅读有多个await方法方法时,程序的实际流程是怎么样的,理解await的异步 ...

  2. 多线程编程学习笔记——async和await(三)

    接上文 多线程编程学习笔记——async和await(一) 接上文 多线程编程学习笔记——async和await(二) 五.   处理异步操作中的异常 本示例学习如何在异步函数中处理异常,学习如何对多 ...

  3. 多线程编程学习笔记——使用异步IO(一)

    接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...

  4. 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端

    接上文 多线程编程学习笔记——使用异步IO 二.   编写一个异步的HTTP服务器和客户端 本节展示了如何编写一个简单的异步HTTP服务器. 1.程序代码如下. using System; using ...

  5. 多线程编程学习笔记——异步调用WCF服务

    接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...

  6. 多线程编程学习笔记——使用异步IO

    接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...

  7. [Java123] JDBC and Multi-Threading 多线程编程学习笔记

    项目实际需求:DB交互使用多线程实现 多线程编程基础:1.5  :( (假设总分10) 计划一个半月从头学习梳理Java多线程编程基础以及Oracle数据库交互相关的多线程实现 学习如何通过代码去验证 ...

  8. Java多线程编程(学习笔记)

    一.说明 周末抽空重新学习了下多线程,为了方便以后查阅,写下学习笔记. 有效利用多线程的关键是理解程序是并发执行而不是串行执行的.例如:程序中有两个子系统需要并发执行,这时候需要利用多线程编程. 通过 ...

  9. python学习笔记 async and await

    用asyncio提供的@asyncio.coroutine可以把一个generator标记为coroutine类型,然后在coroutine内部用yield from调用另一个coroutine实现异 ...

随机推荐

  1. Linux必知必会的目录与启动过程

    第1章 /etc/目录 1.1 /etc/sysconfig/network-scripts/ifcfg-eth0 linux第一块网卡的配置文件 [root@znix ~]# cat /etc/sy ...

  2. VS2015编译VS2013工程文件出错

    错误:未能从程序集"C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Build.Tasks.v14.0.dll"加载任务工厂&q ...

  3. PHPMailer 发送邮件(二)

    发现PHPMailer又做了较大的更新,以前发送邮件的方法已不太适用,刚好要做一个实验,需要搭建个环境,这里使用Gmail进行测试,现记录下来. 传送地址Github: PHPMailer 基本要求的 ...

  4. C 程序实现密码隐秘输入 linux系统可执行

    读写用户输入,屏幕不回显 char *getpass( const char *prompt); getpass用于从键盘读取用户输入,但屏幕不回显. 参数prompt为屏幕提示字符. 函数返回值为用 ...

  5. hadoop启动name失败

    namenode失败十分的常见, 1.java.io.EOFException; Host Details : local host is: "hadoop1/192.168.41.134& ...

  6. 64位win7下安装Boost 1.59.0 + boost.python 1.59.0 + gccxml + pygccxml + pyplusplus(py++)

    由于安装过程中实在是出现了N多问题,所以不得不专门写个帖子来记录一下这破东西在Win7下的安装过程,避免以后还要再用的时候踩坑. 1.Boost简介 Boost库是一个可移植.提供源代码的C++库,作 ...

  7. Spring配置补充

    # :Spring配置补充 ## 一:灵活配置DataSource (1)    使用属性文件配置数据源 (2)    使用JNDI数据源 (3)    Spring中的Bean的作用域问题, Sin ...

  8. [转载] Redis系统性介绍

    转载自http://blog.nosqlfan.com/html/3139.html?ref=rediszt 虽然Redis已经很火了,相信还是有很多同学对Redis只是有所听闻或者了解并不全面,下面 ...

  9. 下一个计划 : .NET/.NET Core应用性能管理系统

    前言 最近几个月一直在研究开源的APM和监控方案,并对比使用了Zipkin,CAT,Sky-walking,PinPoint(仅对比,未实际部署),Elastic APM,TICK Stack,Pro ...

  10. Bootstrap里的文件分别表示什么?都有什么用?

    bootstrap.css 是完整的bootstrap样式表,未经压缩过的,可供开发的时候进行调试用bootstrap.min.css 是经过压缩后的bootstrap样式表,内容和bootstrap ...