前言

什么是TPL?全称:transmission control protocol

传输层对应于OSI七层参考模型的传输层,它提供两种端到端的通信服务。

然后思维方式回到为什么有这个TPL 数据流上。

  1. TPL 数据流库向具有高吞吐量和低滞后时间的占用大量 CPU I/O 操作的应用程序的并行化和消息传递提供了基础。 它还能显式控制缓存数据的方式以及在系统中移动的方式。
  2. 为了更好地了解数据流编程模型,请考虑一个以异步方式从磁盘加载图像并创建复合图像的应用程序。
  3. 传统编程模型通常需要使用回调和同步对象(例如锁)来协调任务和访问共享数据。
  4. 通过使用数据流编程模型,您可以从磁盘读取时创建处理图像的数据流对象。
  5. 在数据流模型下,您可以声明当数据可用时的处理方式,以及数据之间的所有依赖项。 由于运行时管理数据之间的依赖项,因此通常可以避免这种要求来同步访问共享数据。
  6. 此外,因为运行时计划基于数据的异步到达,所以数据流可以通过有效管理基础线程提高响应能力和吞吐量。

分析一下,这段话。

TPL 数据流库向具有高吞吐量和低滞后时间的占用大量 CPU 和 I/O 操作的应用程序的并行化和消息传递提供了基础。

解决一个问题就是:

高吞吐量和低滞后时间的占用大量 CPU 和 I/O 操作的应用程序。

如何解决的:

应用程序的并行化和消息传递提供了基础。通过并行解决的。

例子:

异步方式从磁盘加载图像并创建复合图像的应用程序

遇到的问题:

协调任务和访问共享数据 需要 回调和同步。

就是说共享数据的时候,需要同步。

总结问题:共享数据代价大。

如果解决的:

由于运行时管理数据之间的依赖项,因此通常可以避免这种要求来同步访问共享数据。

总结:解决了依赖,那么不需要同步了。

综上所述:TPL 数据流库的作用在于解决数据之间的依赖,避免同步访问共享数据。

正文

链接数据流块

  1. var multiplyBlock = new TransformBlock<int, int>(item=>item*2);
  2. var subtractBlock = new TransformBlock<int, int>(item=> { Console.WriteLine(item); return item - 2; });
  3. multiplyBlock.LinkTo(subtractBlock);
  4. multiplyBlock.Post(10);
  5. Console.ReadKey();

打印出来就是20了。

传递出错信息

需要处理数据流网格中发生的错误

如果数据流块的委托抛出异常,这个块就是故障块。一但数据流进入了故障状态,就会删除所有数据(停止接收新的数据)。

什么意思呢?

  1. static async void datalfow()
  2. {
  3. var multiplyBlock = new TransformBlock<int, int>(item =>
  4. {
  5. if (item == 1)
  6. {
  7. throw new InvalidOperationException("not good");
  8. }
  9. return item * 2;
  10. }
  11. );
  12. var subtractBlock = new TransformBlock<int, int>(item => { Console.WriteLine(item); return item - 2; });
  13. multiplyBlock.LinkTo(subtractBlock, new DataflowLinkOptions { PropagateCompletion = true});
  14. try
  15. {
  16. multiplyBlock.Post(10);
  17. multiplyBlock.Post(1);
  18. multiplyBlock.Post(20);
  19. await subtractBlock.Completion;
  20. }
  21. catch(AggregateException e)
  22. {
  23. Console.WriteLine(e);
  24. }
  25. }

结果是:



有没有发现multiplyBlock.Post(20);,没有运行?

因为一但一个有错误,那么就会终止,并销毁数据。

这里和上面不同的是,new DataflowLinkOptions { PropagateCompletion = true}。

多个这个东西,那么这个有啥用呢?

因为我们链接块的时候,这个库不会帮助我们传递块运行的状态,如果不传递的话,下一个块是不晓得上一个块到底啥情况,这样不利于我们捕获异常。

而这种传递做法,我们只要在最后的处理模块,统一处理错误就可以。

断开链接

这个我从来就没有遇到过。是这样子的,适用一种这样的场景。

比如说有一个数据块需要动态替换,需要断开现有的模块然后接上新的数据块。

  1. static async void datalfow()
  2. {
  3. var multiplyBlock = new TransformBlock<int, int>(item =>
  4. {
  5. if (item == 1)
  6. {
  7. throw new InvalidOperationException("not good");
  8. }
  9. Console.WriteLine("item:" + item);
  10. return item * 2;
  11. }
  12. );
  13. var subtractBlock = new TransformBlock<int, int>(item => { Console.WriteLine(item-2); return item - 2; });
  14. var appendBlock = new TransformBlock<int, int>(item => { Console.WriteLine(item+2); return item + 2; });
  15. var link=multiplyBlock.LinkTo(subtractBlock, new DataflowLinkOptions { PropagateCompletion = true});
  16. try
  17. {
  18. for (int i = 0; i < 20; i++)
  19. {
  20. multiplyBlock.Post(2);
  21. if (i==10)
  22. {
  23. await Task.Delay(1000);
  24. link.Dispose();
  25. multiplyBlock.LinkTo(appendBlock, new DataflowLinkOptions { PropagateCompletion = true });
  26. }
  27. }
  28. await subtractBlock.Completion;
  29. }
  30. catch(AggregateException e)
  31. {
  32. Console.WriteLine(e);
  33. }
  34. }

结果是:

值得注意的是,我这里了一个:

  1. await Task.Delay(1000);

这是模拟动态运行的时候,因为当我post结束的时候,数据块链接还没开始传递。

注:

  1. 除非保证链接是空闲的情况下,否则在断开数据块的链接时候会出现竞争。
  2. 竞争的是先断开还是先传递。
  3. 但是这种竞争是安全的,他会保证要不断开,要不传递带下一个数据块。

限制流量

前面我们都是线性链接,就是一条路走到黑。但是呢,有时候出现分叉的时候,那么该如何均衡呢?

之所以考虑均衡,是因为比如传递到下一个数据块的时候,是会有缓存的。如果有条分叉,一条分叉无限去缓存,那另外一条可能吃不上饭了。

  1. static async void datalfow()
  2. {
  3. var multiplyBlock = new TransformBlock<int, int>(item =>
  4. {
  5. if (item == 1)
  6. {
  7. throw new InvalidOperationException("not good");
  8. }
  9. Console.WriteLine("item:" + item);
  10. return item * 2;
  11. }
  12. );
  13. var subtractBlock = new TransformBlock<int, int>(item => { Console.WriteLine(item-2); return item - 2; });
  14. var appendBlock = new TransformBlock<int, int>(item => { Console.WriteLine(item+2); return item + 2; });
  15. multiplyBlock.LinkTo(subtractBlock, new DataflowLinkOptions { PropagateCompletion = true});
  16. multiplyBlock.LinkTo(appendBlock, new DataflowLinkOptions { PropagateCompletion = true });
  17. try
  18. {
  19. for (int i = 0; i < 100; i++)
  20. {
  21. multiplyBlock.Post(2);
  22. }
  23. await subtractBlock.Completion;
  24. }
  25. catch(AggregateException e)
  26. {
  27. Console.WriteLine(e);
  28. }
  29. }

这种就属于没吃上饭的情况。

  1. static async void datalfow()
  2. {
  3. var multiplyBlock = new TransformBlock<int, int>(item =>
  4. {
  5. if (item == 1)
  6. {
  7. throw new InvalidOperationException("not good");
  8. }
  9. Console.WriteLine("item:" + item);
  10. return item * 2;
  11. }
  12. );
  13. var options = new DataflowBlockOptions {BoundedCapacity=1 };
  14. var subtractBlock = new TransformBlock<int, int>(item => {
  15. return item - 2;
  16. }, options);
  17. var appendBlock = new TransformBlock<int, int>(item => { Console.WriteLine(item+2); return item + 2; }, options);
  18. multiplyBlock.LinkTo(subtractBlock, new DataflowLinkOptions { PropagateCompletion = true});
  19. multiplyBlock.LinkTo(appendBlock, new DataflowLinkOptions { PropagateCompletion = true });
  20. try
  21. {
  22. for (int i = 0; i < 100; i++)
  23. {
  24. multiplyBlock.Post(2);
  25. }
  26. await subtractBlock.Completion;
  27. }
  28. catch(AggregateException e)
  29. {
  30. Console.WriteLine(e);
  31. }
  32. }

限制缓存为1,那么这时候我们就会相互切换。

下一章

整理:

1.数据流块的并行处理

2.创建自定义数据流块

参考

https://www.cnblogs.com/yswenli/p/8042594.html

并发系列64章(TPL 数据流)第七章的更多相关文章

  1. IDEA第七章----插件

    idea的另一个可爱之处,就是它的强大的插件,下面我以CodeGlance插件为例,这个可以快速定位代码 第一节:安装插件 ● All plugins 显示所有插件. ● Enabled 显示当前所有 ...

  2. 《Entity Framework 6 Recipes》中文翻译系列 (38) ------ 第七章 使用对象服务之动态创建连接字符串和从数据库读取模型

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第七章 使用对象服务 本章篇幅适中,对真实应用中的常见问题提供了切实可行的解决方案. ...

  3. 《Entity Framework 6 Recipes》中文翻译系列 (41) ------ 第七章 使用对象服务之标识关系中使用依赖实体与异步查询保存

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 7-7  标识关系中使用依赖实体 问题 你想在标识关系中插入,更新和删除一个依赖实体 ...

  4. [书籍翻译] 《JavaScript并发编程》第七章 抽取并发逻辑

    本文是我翻译<JavaScript Concurrency>书籍的第七章 抽取并发逻辑,该书主要以Promises.Generator.Web workers等技术来讲解JavaScrip ...

  5. jQuery系列 第七章 jQuery框架DOM操作

    第七章 jQuery框架的选择器 jQuery框架继承和优化了JavaScript访问DOM对象的特性,我们使用jQuery框架提供的api可以更加方便的操作DOM对象. 7.1 创建DOM节点 使用 ...

  6. 第七章 Rocketmq--消息驱动

    今天咱们接着 上一篇第六章 Sleuth–链路追踪 继续写 SpringCloud Alibaba全家桶 , 第七章 Rocketmq--消息驱动,废话不多说,开始了 7.1 MQ简介 7.1.1 什 ...

  7. C primer plus 读书笔记第六章和第七章

    这两章的标题是C控制语句:循环以及C控制语句:分支和跳转.之所以一起讲,是因为这两章内容都是讲控制语句. 第六章的第一段示例代码 /* summing.c --对用户输入的整数求和 */ #inclu ...

  8. 【原创】构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)—托管资源优化—监测CLR性能

    原文:[原创]构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)-托管资源优化-监测CLR性能 构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)—托管资源优化—监测C ...

  9. 第七章——DMVs和DMFs(4)——用DMV和DMF监控磁盘IO

    原文:第七章--DMVs和DMFs(4)--用DMV和DMF监控磁盘IO 前言: 本文为本系列最后一篇,作为DBA,你必须经常关注磁盘的I/O问题,一旦出现问题,要尽快分析出是什么问题.SQLServ ...

随机推荐

  1. EPX Studio开发平台简介

    大家问我最多的问题就是“EPX 是什么?”“EPX 能够用来做什么?”“EPX 有什么优势?”“EPX 与其它开发平台的区别是什么?” 问题林林总总,总也回答不完,希望通过正文前面的这段文字,来简要回 ...

  2. 3. webdriver的常用方法

    WebDriver常用方法: clear(): 清除文本. send_keys (value): 模拟按键输入. click(): 单击元素. submit():用于提交表单 from seleniu ...

  3. Swift 4.0 字符串(String)学习

    定义字符串常量(常量只有读操作) let lString = "constant" let lString1: String = "constant" 定义字符 ...

  4. hdu2087kmp模板练习

    题目网址:http://icpc.njust.edu.cn/Problem/Hdu/2087/ 代码: #include<bits/stdc++.h> using namespace st ...

  5. 翻转-Flip Columns For Maximum Number of Equal Rows

    2020-02-20 11:00:06 问题描述: 问题求解: 翻转题一个常见的思路就是站在结束的状态来反推最初的状态,本题的解题思路就是站在结束的时候的状态来进行反推. 如果在最终的状态i-row是 ...

  6. C# NAudio录音和播放音频文件及实时绘制音频波形图(从音频流数据获取,而非设备获取)

    下午写了一篇关于NAudio的录音.播放和波形图的博客,不太满意,感觉写的太乱,又总结了下 NAudio是个相对成熟.开源的C#音频开发工具,它包含录音.播放录音.格式转换.混音调整等功能.本次介绍主 ...

  7. SpringBoot项目中应用Jedis和一些常见配置

    优雅的使用Jedis Redis的Java客户端有很多,Jedis是其中使用比较广泛和性能比较稳定的一个.并且其API和RedisAPI命名风格类似,推荐大家使用 在项目中引入Jedis 可以通过Ma ...

  8. excel中存储的icount,赋值完之后

    最近需要实现一个功能,为了确保每次函数运行的时候count是唯一的,所以想读取excel中存储的icount,赋值完之后对其进行+1操作,并存入excel文件,确保下次读取的count是新的,没有出现 ...

  9. 使用Keras构建深度图像搜索引擎

    动机 想象一下,如果有数十万到数百万张图像的数据集,却没有描述每张图像内容的元数据.我们如何建立一个系统,能够找到这些图像的子集来更好地回答用户的搜索查询? 我们基本上需要的是一个搜索引擎,它能够根据 ...

  10. PyTorch专栏(六): 混合前端的seq2seq模型部署

    欢迎关注磐创博客资源汇总站: http://docs.panchuang.net/ 欢迎关注PyTorch官方中文教程站: http://pytorch.panchuang.net/ 专栏目录: 第一 ...