当前位置: 首页 > news >正文

C# 异步编程(并行循环)

并行循环

本节将简要介绍任务并行库(Task Parellel Library)。它是BCL中的一个类库,极大地简化了
并行编程。本章无法尽述其细节,这里只介绍其中两个简单的结构,你可以轻松快速地掌握并用,它们是Parallel.For循环和ParalleI.ForEach循环。这两个结构位于system.Threading.Tasks命名
空间中。

至此,相信你应该很熟悉c#的标准for和foreach循环了。这两个结构非常普遍,且极其强
大。许多时候,在使用这两个结构时,每一次迭代都依赖于前一次迭代的计算或行为。但有的时
候又不是这样。如果迭代之间彼此独立,并且程序运行在多处理器机器上,那么若能将不同的迭
代放在不同的处理器上并行处理的话,将会获益匪浅。Parallel.For和Parallel.ForEach结构就
是这样做的。

这两个结构的形式是包含输人参数的方法。Parallel.For方法有12个重载,其中最简单的
那个的签名如下。
publicstaticParallelLoopResult.(int fromInclusive,int toExclusive,Action body)

  • fromlnclusive参数是迭代系列的第一个整数。
  • toExclusive参数是比迭代系列最后一个索引号大1的整数。也就是说,和使用表达式
    index<ToExclusive计算一样。
  • body是接受单个输入参数的委托,body的代码在每一次迭代中执行一次。
    如下代码是使用Parallel.For结构的例子。它从0迭代到14(记住实际的参数巧超出了最
    大迭代索引)并且打印出迭代索引和索引的平方。该应用程序满足各个迭代之间相互独立的条件。
    还要注意,必须使用System.Threading.Tasks命名空间。
using System;
using System.Threading.Tasks;namespace ExampleParallerFor
{class Program{static void Main(){Parallel.For(0,15,i=>Console.WriteLine($"The square of{i} is{i*i}"));}}
}

另一个示例如下。程序以并行方式填充一个整数数组,把值设置为迭代索引号的平方。

class Program
{static void Main(){const int maxValues=50;int[] squares=new int[maxValues];Parallel.For(0,maxValues,i+>squares[i]=i*i);}
}

在本例中,尽管迭代可能并行执行,也能以任意顺序执行,但是最后结果始终是一个包含前
50个平方数的数组一一并且按顺序排列。
另外一个并行循环结构是Parallel.ForEach方法。该方法有相当多的重载,其中最简单的如下:

  • TSource是集合中对象的类型;
  • source是TSource对象的集合·
  • body是要应用到集合中每一个元素上的Lambda表达式。
static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource>source,Action<TSource>boday)

使用Paralle.ForEach方法的例子如下。在这里,TSource是string,source是string[]。

using System;
using System.Threading.Tasks;namespace ParallelForeach1
{class Program{static void Main(){string[] squares=new string[]{"We","hold","these","truths","to","be","self-evident","that","all","men","are","created","equal"};Parallel.ForEach(squares,s=>Console.WriteLine(string.Format($"\"{s}\" has{s.Length}letters")));}}
}

在我的双核处理器pc上运行这段代码时产生了如下输出,但是每一次运行都可能会有不一
样的顺序。

其他异步编程模式

如果我们要自己编写异步代码,最可能使用的就是本章前面介绍的async/await特性和
BackgroundWorker类,或者任务并行库。然而,你仍然有可能需要使用旧的模式来产生异步代码。
为了完整性,我们从现在开始介绍这些模式,直到本章结束。在学习了这些旧模式后,你将对
async/await特性是多么简单有更加深刻的认识。

第14章介绍了委托,我们了解到当委托对象被调用时,它调用其调用列表中包含的方法。
就像程序调用方法一样,这是同步完成的。

如果委托对象在调用列表中只有一个方法(之后会叫作引用方法),它就可以异步执行这个
方法。委托类有两个方法,叫作BeginInvcke和Endlnvoke,它们就是用来实现这个目的的。这
两个方法以如下方式使用。

  • 当调用委托的BeginInvoke方法时,它开始在一个独立线程上执行引用方法,之后立即
    返回到原始线程。原始线程可以继续,而引用方法会在线程池的线程中并行执行。
  • 当程序希望获取已完成的异步方法的结果时,可以检查BeginInvoke返回的IAsyncResult
    的IsCompleted属性,或调用委托的EndInvoke方法来等待委托完成。

图21-19演示了使用这一过程的三种标准模式。对于这三种模式来说,原始线程都发起了一
个异步方法调用,然后做一些其他处理。然而,这些模式的区别在于,原始线程如何知道发起的
线程已经完成。

  • 在等待直到完成(wait-until-done)模式中,在发起了异步方法以及做了一些其他处理之
    后,原始线程就中断并且等异步方法完成之后再继续。
  • 在轮询(polling)模式中,原始线程定期检查发起的线程是否完成,如果没有则可以继续
    做一些其他的事情。
  • 在回调(callback)模式中,原始线程一直执行,无须等待或检查发起的线程是否完成。
    在发起的线程中的引用方法完成之后,发起的线程就会调用回调方法,由回调方法在调
    用EndInvoke之前处理异步方法的结果。

异步方法调用的标准模式

http://www.dtcms.com/a/324769.html

相关文章:

  • 内存溢出的原因有哪些,如何排查线上问题?
  • 【Spring Boot刷新上下文核心流程详解】
  • UNIVERSAL IMAGE RESTORATION PRE-TRAINING VIA DEGRADATION CLASSIFICATION
  • 【Python 工具人快餐 · 第 5 份】
  • 1. 电阻选型
  • 云服务器最新版MySQL 安装步骤
  • jdk17下载安装教程【超详细图文】
  • 零基础学习jQuery第二天
  • 在windows安装colmap并在cmd调用
  • json-fortran库的使用
  • TS 编译原理,提供的 API
  • Angular初学者入门第二课——.ts、.d.ts、.state.ts的区别(精品)
  • Perplexity 为特朗普 Truth Social 提供技术支持
  • 深入解析微服务分布式事务的原理与优化实践
  • 极移(Polar Motion):概念、原因、影响及坐标转换计算
  • 下载UOS桌面专业版系统镜像
  • 计算机视觉(CV)——图像相关基本概念
  • 【redis初阶】------redis客户端(1)
  • Node.js面试题及详细答案120题(01-15) -- 基础概念篇
  • Leaflet地图高亮与编辑功能实现
  • 【最后203篇系列】031 构建MCP尝试
  • signed 和 unsigned 类型说明符
  • 嵌套-列表存储字典,字典存储列表,字典存储字典
  • Linux 路由子系统深度分析:框架、实现与代码路径
  • web刷题3
  • 商业解决方案技术栈总结
  • Python 获取对象信息的所有方法
  • 基于Spring Boot和SSE的实时消息推送系统
  • 三数之和 Java
  • 人工智能系列(7)人工神经网络中的无监督学习