使用条件

1、必须熟练掌握锁、死锁、task的知识,他是建立这两个的基础上的。task建立在线程和线程池上的。

2、并不是所有代码都适合并行化。 例如,如果某个循环在每次迭代时只执行少量工作,或它在很多次迭代时都不运行,那么并行化的开销可能导致代码运行更慢。

3、 Parallel.For()和Paraller.ForEach()方法在每次迭代中调用相同的代码,都有返回值ParallelLoopResult 。而Parallel.Invoke()方法允许同时调用不同的方法,返回值viod。

4、 ForEach的格式【Item、否是带有并行选项、【Item 、否是有循环状态、否是有索引 、否是有线程本地变量 】】

For的格式【起始索(引包含),结束索引(不包含),是否有并行选项【起始索引,释放有循环状态,否是有线程本地变量】】

总结

1、C#通过Parallel类提供并行任务支持,可以很简单的使用线程池

2、要注意的是,Parallel不保障执行顺序

相关的类:

Parallel
ParallelLoopResult
ParallelLoopState
ParallelOptions

For的格式【起始索(引包含),结束索引(不包含),释放有并行选项【起始索引,释放有循环状态,是否线程本地变量】】

用法一、For(Int32, Int32, Action<Int32>)

int[] count  = Enumerable.Range(1, 100).ToArray();
Parallel.For(1, count.Length, indexer => { Console.WriteLine(indexer); });

用法二、For(Int32, Int32, Action<Int32,ParallelLoopState>)

ParallelOptions op = new() { CancellationToken = CancellationToken.None };
Parallel.For(1, 2, (indexer, op) => { Console.WriteLine(indexer); });

用法三、For(Int32, Int32, ParallelOptions, Action<Int32,ParallelLoopState>)

ParallelOptions op = new() { CancellationToken = CancellationToken.None };
op.TaskScheduler = TaskScheduler.Default;
op.MaxDegreeOfParallelism = 1;
Parallel.For(1, 2, op, indexer => { Console.WriteLine(indexer); });

用法四、

编写具有线程局部变量的 Parallel.For 循环

public static ParallelLoopResult For<TLocal>
(
int fromInclusive, //范围下线 包含
int toExclusive, //范围上线 不包含
Func<TLocal> localInit,//TLocal表示线程本地变量的类型
Func<int, ParallelLoopState, TLocal, TLocal> body,//TLocal表示线程本地变量的类型
Action<TLocal> localFinally
)

案例:

//TLocal   线程本地 变量的类型
int totalSum = 0;
Parallel.For<string>(1, 10,
()=> "开始打印",// "开始打印" 被保存到线程本地变量中
(indexer,loopState, LocalValue) =>
{
Console.WriteLine(LocalValue +" Thread "+ indexer );
return LocalValue += indexer; // LocalValue += indexer被保存到线程本地变量中
}, LocalValue => Console.WriteLine("结束打印")
);
/*
输出
开始打印 Thread 1
开始打印 Thread 2
开始打印2 Thread 8 return LocalValue += indexer;被存储到本地线程变量中LocalValue,
开始打印28 Thread 9 所以打印出 开始打印28
开始打印 Thread 6
开始打印 Thread 5
结束打印
开始打印1 Thread 7
结束打印
开始打印 Thread 3
结束打印
结束打印
开始打印 Thread 4
结束打印
结束打印*/

ForEach的格式【Item、否是带有并行选项、【Item 、否是有循环状态、否是有索引 、否是有线程本地变量 】】

Enumerable<TSource>和 Partitioner<TSource> 都是以下格式

ForEach<TSource>(IEnumerable<TSource>, ParallelOptions, Action<TSource>)
ForEach<TSource>(IEnumerable<TSource>, ParallelOptions, Action<TSource,ParallelLoopState>)

ForEach<TSource>(IEnumerable<TSource>, Action<TSource>)
ForEach<TSource>(IEnumerable<TSource>, Action<TSource,ParallelLoopState>)
ForEach<TSource>(IEnumerable<TSource>, Action<TSource,ParallelLoopState,Int64>)
ForEach<TSource>(IEnumerable<TSource>, ParallelOptions, Action<TSource,ParallelLoopState,Int64>)

ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>)
ForEach<TSource,TLocal>(IEnumerable<TSource>,
Func<TLocal>,
Func<TSource,ParallelLoopState,Int64,TLocal,TLocal>,
Action<TLocal>)
ForEach<TSource,TLocal>(IEnumerable<TSource>,
ParallelOptions, Func<TLocal>,
Func<TSource,ParallelLoopState,TLocal,TLocal>,
Action<TLocal>)
ForEach<TSource,TLocal>(IEnumerable<TSource>,
ParallelOptions, Func<TLocal>,
Func<TSource,ParallelLoopState,Int64,TLocal,TLocal>,
Action<TLocal>)

用法一:Item

ForEach<TSource>(IEnumerable<TSource>, Action<TSource>)案例如下:

string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
Parallel.ForEach(data, item => { Console.WriteLine(item); });

用法二:Item 、循环状态、带索引

ForEach<TSource>(IEnumerable<TSource>, Action<TSource,ParallelLoopState,Int64(索引)>)案例如下:

string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
Parallel.ForEach(data, (item,loopstate,indexer )=>
{
if(item == "three")
{ loopstate.Break();
Console.WriteLine($"item:{item} index:{indexer} ShouldExitCurrentIteration:{loopstate.ShouldExitCurrentIteration} LowestBreakIteration(索引):{loopstate.LowestBreakIteration}");
}
Console.WriteLine($"item:{item} index:{indexer}" );
});

用法三:Item、带有并行选项、循环状态、索引

ForEach<TSource>(IEnumerable<TSource>, ParallelOptions, Action<TSource,ParallelLoopState,Int64>)案例如下:

string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
ParallelOptions op = new();
op.TaskScheduler = TaskScheduler.Default;//默认的任务调度器
op.MaxDegreeOfParallelism = 5;//并行度
op.CancellationToken=CancellationToken.None;//禁止取消
Parallel.ForEach(data, op, (item,loopstate,indexer )=>
{
if(item == "zero")
{ loopstate.Break();
Console.WriteLine($"item:{item} index:{indexer} ShouldExitCurrentIteration:{loopstate.ShouldExitCurrentIteration} LowestBreakIteration:{loopstate.LowestBreakIteration}");
}
Console.WriteLine($"item:{item} index:{indexer}" );
});

用法四:Item、带有并行选项、循环状态、 线程本地变量

ForEach<TSource,TLocal>(IEnumerable<TSource>, ParallelOptions, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>)案例如下:

string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
ParallelOptions op = new();
op.TaskScheduler = TaskScheduler.Default;//默认的任务调度器
op.MaxDegreeOfParallelism = 5;//并行度
op.CancellationToken=CancellationToken.None;//禁止取消
//自行推断TSource,TLocal
Parallel.ForEach(data, op,
()=>"开始输出:",//初始化线程本地变量 (item,loopstate, TLocal) =>
{
if(item == "zero")
{ loopstate.Break();
Console.WriteLine($"item:{item} index:{TLocal} ShouldExitCurrentIteration:{loopstate.ShouldExitCurrentIteration} LowestBreakIteration:{loopstate.LowestBreakIteration}");
return TLocal+ "=>Break";
}
Console.WriteLine($"item:{item} index:{TLocal}" );
return TLocal + "=>complete";
},
local => Console.WriteLine(local) //输出线程本地变量 );

用法五:Item、带有并行选项、循环状态、索引、 线程本地变量

ForEach<TSource,TLocal>(IEnumerable<TSource>, ParallelOptions, Func<TLocal>, Func<TSource,ParallelLoopState,Int64,TLocal,TLocal>, Action<TLocal>)

string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
ParallelOptions op = new();
op.TaskScheduler = TaskScheduler.Default;//默认的任务调度器
op.MaxDegreeOfParallelism = 5;//并行度
op.CancellationToken=CancellationToken.None;//禁止取消
//自行推断TSource,TLocal
Parallel.ForEach(data, op,
()=>"开始输出:",//初始化线程本地变量 (item,loopstate, index, TLocal) =>
{
if(item == "zero")
{ loopstate.Break();
Console.WriteLine($"item:{item} index:{TLocal} ShouldExitCurrentIteration:{loopstate.ShouldExitCurrentIteration} LowestBreakIteration:{loopstate.LowestBreakIteration}");
return TLocal+ "=>Break";
}
Console.WriteLine($"item:{item} index:{TLocal}" );
return TLocal + "=>complete";
},
local => Console.WriteLine(local) //输出线程本地变量 );

用法六:Item 、循环状态、 线程本地变量

ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>)案例如下:

string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };

//自行推断TSource,TLocal
Parallel.ForEach(data,
()=>"开始输出:",//初始化线程本地变量 (item,loopstate, TLocal) =>
{
if(item == "zero")
{ loopstate.Break();
Console.WriteLine($"item:{item} index:{TLocal} ShouldExitCurrentIteration:{loopstate.ShouldExitCurrentIteration} LowestBreakIteration:{loopstate.LowestBreakIteration}");
return TLocal+ "=>Break";
}
Console.WriteLine($"item:{item} index:{TLocal}" );
return TLocal + "=>complete";
},
local => Console.WriteLine(local) //输出线程本地变量 );

用法七:Item 、循环状态、索引、 线程本地变量

ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,Int64,TLocal,TLocal>, Action<TLocal>)

string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };

//自行推断TSource,TLocal
Parallel.ForEach(data,
()=>"开始输出:",//初始化线程本地变量 (item,loopstate, TLocal,index) =>
{
if(item == "zero")
{ loopstate.Break();
Console.WriteLine($"item:{item} index:{TLocal} ShouldExitCurrentIteration:{loopstate.ShouldExitCurrentIteration} LowestBreakIteration:{loopstate.LowestBreakIteration}");
return TLocal+ "=>Break";
}
Console.WriteLine($"item:{item} index:{TLocal}" );
return TLocal + "=>complete";
},
local => Console.WriteLine(local) //输出线程本地变量 );

Invoke

Invoke(Action[])  :尽可能并行执行提供的每个操作。 返回值Viod

Parallel.Invoke(
() => Console.WriteLine("sfsfsdfsdf1"),
() => Console.WriteLine("sfsfsdfsdf2"),
() => Console.WriteLine("sfsfsdfsdf3")
);

Invoke(ParallelOptions, Action[]) :执行所提供的每个操作,而且尽可能并行运行,除非用户取消了操作。返回值Viod

ParallelOptions op = new();
op.TaskScheduler = TaskScheduler.Default;//默认的任务调度器
op.MaxDegreeOfParallelism = 5;//并行度
op.CancellationToken = CancellationToken.None;//禁止取消
Parallel.Invoke(
() => Console.WriteLine("sfsfsdfsdf1"),
() => Console.WriteLine("sfsfsdfsdf2"),
() => Console.WriteLine("sfsfsdfsdf3")
);


【C# Parallel】开端的更多相关文章

  1. ej3-0开端

    开始 编码多年,总有一些最佳实践,Java也是,比如设计模式,比如Effective Java 3 (ej3) . 设计模式先后看过<大话设计模式>,<HeadFirst 设计模式& ...

  2. .Net多线程编程—System.Threading.Tasks.Parallel

    System.Threading.Tasks.Parallel类提供了Parallel.Invoke,Parallel.For,Parallel.ForEach这三个静态方法. 1 Parallel. ...

  3. Java 8函数编程轻松入门(五)并行化(parallel)

    1.并发与并行的区别 并发: 一个时间段内有几个程序都处于已启动到运行完毕之间,且这几个程序都是在同一个处理机上运行.但在任一个时刻点只有一个程序在处理机上运行 并行: 在同一个时刻,多核处理多个任务 ...

  4. Parallel并行之乱用

    关于Parallel我也不细说了,一则微软封装的很好用,二来介绍这个的遍地都是. 我要说的是,要想成为一个优秀的标题党,一定要把重点放到别的地方,为了节省大家阅读时间,我先把结论说了,然后再慢慢从头说 ...

  5. 代码的坏味道(12)——平行继承体系(Parallel Inheritance Hierarchies)

    坏味道--平行继承体系(Parallel Inheritance Hierarchies) 平行继承体系(Parallel Inheritance Hierarchies) 其实是 霰弹式修改(Sho ...

  6. 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel)

    Task - 基于线程池的任务(在 System.Threading.Tasks 命名空间下) 多 Task 的并行执行 Parallel - 并行计算(在 System.Threading.Task ...

  7. Parallel.Foreach

    随着多核时代的到来,并行开发越来越展示出它的强大威力! 使用并行程序,充分的利用系统资源,提高程序的性能.在.net 4.0中,微软给我们提供了一个新的命名空间:System.Threading.Ta ...

  8. 在Parallel中使用DbSet.Add()发现的一系列多线程问题和解决过程

    发现问题 需求很简单,大致就是要批量往数据库写数据,于是打算用Parallel并行的方式写入,希望能利用计算机多核特性加快程序执行速度.想的很美好,于是快速撸了类似下面的一串代码: using (va ...

  9. F#之旅0 - 开端

    F#之旅0 - 开端 UWP的学习告一段落,CozyRSS的UWP版本并没有做.UWP跟wpf开发几乎一模一样,然后又引入了很多针对移动设备的东西,这部分有点像android.没啥太大的意思,不难,估 ...

随机推荐

  1. golang中通过递归或通道实现斐波那契数列

    1. 循环实现 package main import "fmt" func fibonacciFor(nums int) (s1 []int) { // 循环实现斐波那切数列 n ...

  2. SaltStack 的基本概念与工作原理 架构设计

    随着云计算技术的快速普及与发展,越来越多的企业开始学习和搭建自己的云平台代替传统的 IT 交付模式,企业的 IT 环境也随之越来越复杂,常规的运维方法与技术已经无法满足现在云环境中系统的配置与变更.基 ...

  3. 洛谷P1002过河卒java100分题解

    题目描述如图: 这道题我以前以回溯的方法做,只能拿到60分 现在才发现是道动态规划题 解题思路: 创建一个(0,0)到终点打小的二维数组表示棋盘 每个坐标的值为此位置到终点的路数 最下方一排和最右方一 ...

  4. Visualizing and Understanding Convolutional Networks论文复现笔记

    目录 Visualizing and Understanding Convolutional Networks 论文复现笔记 Abstract Introduction Approach Visual ...

  5. 《Spring Boot 实战纪实》之过滤器

    导航 什么是过滤器 Spring的过滤器 Filter定义 过滤的对象 典型应用 过滤器的使用 Filter生命周期 过滤器链 自定义敏感词过滤器 新增自定义过滤器 添加 @WebFilter注解 添 ...

  6. 010 Linux 文本统计与去重 (wc 和 uniq)

    wc 命令一般是作为组合命令的一员与其他命令一同起到统计的作用.而一般情况下使用wc -l 命令较多. uniq 可检查文本文件中重复出现的行,一般与 sort 命令结合使用.一起组合搭配使用完成统计 ...

  7. 如何在pyqt中使用 QGraphicsView 实现图片查看器

    前言 在 PyQt 中可以使用很多方式实现照片查看器,最朴素的做法就是重写 QWidget 的 paintEvent().mouseMoveEvent 等事件,但是如果要在图像上多添加一些形状,那么在 ...

  8. LCT 入门

    这是一份 \(\rm LCT\) 入门总结. 关于 \(\rm LCT\) 的复杂度这里不会提及,只会记录 \(\rm LCT\) 的基本操作和经典例题,但神奇的 \(\rm LCT\) 虽然常数巨大 ...

  9. WebService、Http请求、Socket请求

    WebService 定义 一种web程序访问方式,常见协议:SOAP(简单对象访问协议),其实就是Http+XML.利用对象进行数据交互. 请求方法 import lombok.extern.slf ...

  10. spring学习四:Spring中的后置处理器BeanPostProcessor

    BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化.配置以及其他初始化方法前后要添加一些自己逻辑处理.我们需要定义一个或多个BeanPostProcesso ...