接上文 多线程编程学习笔记——async和await(一)

三、   对连续的异步任务使用await操作符

本示例学习如何阅读有多个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)
{

Console.WriteLine(string.Format("----- 对连续的异步任务使用await操作符----"));

            Task t = AsyncWithTPL();
t.Wait();
t = AsyncWithAwait();
t.Wait();
Console.Read();
} static Task AsyncWithTPL()
{
var containerTask = new Task(() =>
{
Task<string> task1 = GetInfoAsync("TPL Task 1"); task1.ContinueWith(task =>
{
Console.WriteLine(task1.Result); Task<string> task2 = GetInfoAsync("TPL Task 2");
task2.ContinueWith(innerTask =>
Console.WriteLine(innerTask.Result), TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.AttachedToParent); task2.ContinueWith(innerTask =>
Console.WriteLine(innerTask.Exception.InnerException), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent); }, TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.AttachedToParent);
task1.ContinueWith(task =>
Console.WriteLine(task1.Exception.InnerException), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent);
}
);
containerTask.Start();
return containerTask;
}
async static Task AsyncWithAwait()
{
try
{
string result = await GetInfoAsync("Async Task 1");
Console.WriteLine(result);
result = await GetInfoAsync("Async Task 2");
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
} async static Task<string> GetInfoAsync(string name)
{
Console.WriteLine(string.Format("任务 {0} 开始。。。",name));
await Task.Delay(TimeSpan.FromSeconds());
if(name== "TPL Task 2")
throw new Exception(string.Format("{0} 抛出异常信息!", name));
return string.Format(" Task {0} 正在运行在线程 ID={1}上。这个工作线程是否是线程池中的线程:{2}", name,
Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
}
}
}

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

首先,程序运行时会执行两个异步操作。

  1. AsyncWithAwait方法,它看起来跟平常的代码一样,唯一不同之处就是使用了两个await声明。最重要的一点是代码的执行顺序依然是顺序执行的,调用AsyncWithAwait任务的代码只有等 之前的的任务完成 后才会开始执行。当阅读代码时,程序流很清晰,可以看到什么先执行,什么后执行,但是程序如何异步执行呢?首先,它不是一直是异步执行的,只有当使用await,且一个任务已经完成,我们会异步地得 到这个任务的结果。否则 ,当在代码中看到await声明时,通过的行为是代码执行到await代码行时将立即返回,并且剩下的代码将会在一个后续操作任务中运行。因此等待操作结果时并没有阻塞程序执行,这是一个异步调用 。当AsyncWithAwait方法中的代码执行时,除了在main方法中调用 t.wait外,我们可以执行任务其他任务。但是主线程必须等待直到所有的异步操作完成 ,否则 主线程完成后所有运行异步操作的后台线程会停止运行。
  2. AsyncWithTPL方法模仿了AsyncWithAwait的程序流。我们需要一个容器任务来处理所有相互依赖的任务。然后启动主任务,给其加了一组后续操作。当这个任务完成 后,会打印其结果。然后又启动了一个任务,在这个任务完成后会依次运行更多的后续操作。为了测试对异常的处理,当运行第二个任务时故意抛出了一个异常。并打印出异常信息。这组后续操作创建了与第一个方法中一样的程序流。

二、   对并行执行的异步任务使用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)
{
Console.WriteLine(string.Format("----- 对并行执行的异步任务使用await操作符----"));
Task t = AsyncProcess();
t.Wait();
Console.Read(); } async static Task AsyncProcess()
{ Task<string> task1 = GetInfoAsync("Task 1",); Task<string> task2 = GetInfoAsync("Task 2",);
string[] results = await Task.WhenAll(task1, task2);
foreach (var item in results)
{
Console.WriteLine(item);
}
} async static Task<string> GetInfoAsync(string name,int second)
{
Console.WriteLine(string.Format("任务 {0} 开始。。。",name)); await Task.Delay(TimeSpan.FromSeconds(second));
//await Task.Run(() => Thread.Sleep(TimeSpan.FromSeconds(second));
return string.Format(" Task {0} 正在运行在线程 ID={1}上。这个工作线程是否是线程池中的线程:{2}", name,
Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
}
}
}

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

在AsyncProcess方法中定义了两个异步任务task1,task2,分别运行3秒和5秒。然后使用Task.WhenAll辅助方式得到了两个任务的运行结果,而且只有在所有底层任务完成之后,才会运行。之后我们等待这个组合任务的结果。5秒后,我们获取所有结果,说明了这些任务是同时运行的。

我们仔细观察会发现,这两个任务假托是被线程池中的同一个工作线程执行的。当我们并行运行任务时怎么可能发生这样的情况呢?我们注释掉GetIntroAsync方法中的await Task.Delay代码 行,并解除对await task.run代码行的注释,然后再次运行程序。

我们会看到这种情况下,两个任务会被不同的工作线程执行。不同之处是task.delay在幕后使用了一个计时器,过程如下:从线程池中获取工作线程,它将等待task.delay方法返回结果。然后task.delay方法启动计时器并指定一段代码,这段代码会在计时器时间到了task.delay方法中指定的秒数后被 调用 ,之后,立即将工作线程返回到线程池中。当计时器事件运行时,又从线程池中任意获取一个可用的工作线程(可能跟上次运行的是同一个工作线程),并运行计时器指定的代码。

当使用task.run方法时,从线程池中获取了一个工作线程并将其阻塞几秒,然后获取了第二个工作线程也将其阻塞。在这种情况下,我们消费了两个工作线程,但是什么事情也没做。如下图。比较两者的不同之处,在于两个task运行在不同的线程上。

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

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

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

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

    接上文 多线程编程学习笔记——任务并行库(一) 接上文 多线程编程学习笔记——任务并行库(二) 接上文 多线程编程学习笔记——任务并行库(三) 接上文 多线程编程学习笔记——任务并行库(四) 通过前面 ...

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

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

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

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

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

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

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

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

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

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

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

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

  9. python学习笔记 async and await

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

随机推荐

  1. Equations

    Equations Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  2. 远程连接SQL Server 2014遇到的问题和解决

    在本机可以通过IP地址的数据库引擎登录数据库,可用同网段的其它电脑远程登录一直不成功.查看网上资料,认为是主机防火墙的问题. 在微软网站上查找相关的文档找到了答案.http://msdn.micros ...

  3. CSS浮动(Float)

    定义 浮动会使元素向左或向右移动,其周围的元素也会重新排列: 浮动直到它的外边缘碰到包含框或者另一个浮动框才停止: 浮动之后的元素将围绕它,浮动之前的元素不变: 由于浮动框不在文档的普通流中,所以文档 ...

  4. phpstorm php $post数据为空的原因

    今天拿PHPstoem 写了个PHP的表单插入数据,然后直接在里面一运行,就一直提示什么未定义,其实是因为$_PSOT[] 取不到值. 后面发现原来是直接用phpstorm 运行PHP的话,他会自带端 ...

  5. Spring+MyBatis+SpringMvc整合Demo

    客户关系管理系统demo 项目分析 该demo使用技术及环境:ssm+maven+bootstrap+jsp+mysql+idea+jdk1.8 需求:客户管理,实现客户列表分页显示如下图 项目开始 ...

  6. robotframework自动化系列:随机下拉框

    robotframework自动化系列:随机下拉框 随着项目自动化不断推进,在下拉框定位的时候出现些问题,每次下拉框选择都是相同的下拉选项,如果想每次选择的选项不一样,该如何实现呢,查找了很多资料,没 ...

  7. python实现查有道词典

    因为要考英语四级,所以我今天一大早就起来被英语单词,但是作为英语渣渣的我,只能是在网页上挨个查单词的意思.查的多了,心生厌倦,便想着如何才能在终端下查单词,那样速度不就很快了? NOW,我仔细观察每次 ...

  8. vue 集成 axios 发送post请求 payload导致后台无法接收到数据问题

    vue 集成axios之后,发送的post请求默认为payload 方式. 如果想改为正常的方式,需要增加headers头,并且将发送是数据json格式改为 querystring的方式. 安装依赖 ...

  9. Cordova使用build命令出错: Could not create the Java Virtual Machine.

    这是因为虚拟机内存不足导致的,解决方案如下: _JAVA_OPTIONS=-Xmx512M

  10. 从编辑距离、BK树到文本纠错

    搜索引擎里有一个很重要的话题,就是文本纠错,主要有两种做法,一是从词典纠错,一是分析用户搜索日志,今天我们探讨使用基于词典的方式纠错,核心思想就是基于编辑距离,使用BK树.下面我们来逐一探讨: 编辑距 ...