【C# Parallel】开端
使用条件
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】开端的更多相关文章
- ej3-0开端
开始 编码多年,总有一些最佳实践,Java也是,比如设计模式,比如Effective Java 3 (ej3) . 设计模式先后看过<大话设计模式>,<HeadFirst 设计模式& ...
- .Net多线程编程—System.Threading.Tasks.Parallel
System.Threading.Tasks.Parallel类提供了Parallel.Invoke,Parallel.For,Parallel.ForEach这三个静态方法. 1 Parallel. ...
- Java 8函数编程轻松入门(五)并行化(parallel)
1.并发与并行的区别 并发: 一个时间段内有几个程序都处于已启动到运行完毕之间,且这几个程序都是在同一个处理机上运行.但在任一个时刻点只有一个程序在处理机上运行 并行: 在同一个时刻,多核处理多个任务 ...
- Parallel并行之乱用
关于Parallel我也不细说了,一则微软封装的很好用,二来介绍这个的遍地都是. 我要说的是,要想成为一个优秀的标题党,一定要把重点放到别的地方,为了节省大家阅读时间,我先把结论说了,然后再慢慢从头说 ...
- 代码的坏味道(12)——平行继承体系(Parallel Inheritance Hierarchies)
坏味道--平行继承体系(Parallel Inheritance Hierarchies) 平行继承体系(Parallel Inheritance Hierarchies) 其实是 霰弹式修改(Sho ...
- 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel)
Task - 基于线程池的任务(在 System.Threading.Tasks 命名空间下) 多 Task 的并行执行 Parallel - 并行计算(在 System.Threading.Task ...
- Parallel.Foreach
随着多核时代的到来,并行开发越来越展示出它的强大威力! 使用并行程序,充分的利用系统资源,提高程序的性能.在.net 4.0中,微软给我们提供了一个新的命名空间:System.Threading.Ta ...
- 在Parallel中使用DbSet.Add()发现的一系列多线程问题和解决过程
发现问题 需求很简单,大致就是要批量往数据库写数据,于是打算用Parallel并行的方式写入,希望能利用计算机多核特性加快程序执行速度.想的很美好,于是快速撸了类似下面的一串代码: using (va ...
- F#之旅0 - 开端
F#之旅0 - 开端 UWP的学习告一段落,CozyRSS的UWP版本并没有做.UWP跟wpf开发几乎一模一样,然后又引入了很多针对移动设备的东西,这部分有点像android.没啥太大的意思,不难,估 ...
随机推荐
- 【初体验】macos下android ndk交叉编译hello world,并拷贝到android手机上执行
1.机器上以前安装了java 1.8(貌似android ndk不需要java) 2. 下载android ndk,版本是android-ndk-r14b (比较奇怪,我下载了最新的android-n ...
- spring拦截机制中Filter(过滤器)、interceptor(拦截器)和Aspect(切面)的使用及区别
Spring中的拦截机制,如果出现异常的话,异常的顺序是从里面到外面一步一步的进行处理,如果到了最外层都没有进行处理的话,就会由tomcat容器抛出异常. 1.过滤器:Filter :可以获得Http ...
- golang中自定义实现0当做除数的错误异常处理接口
package main import "fmt" type ZeroDivisor struct { // 定义一个0当做除数的结构体 divisor int // 被除数 di ...
- 将Java连接数据库操作封装到MySQL类中
public class MySQL { final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver"; final String D ...
- TF-IDF计算相似度为什么要对稀疏向量建立索引?
TF-IDF的向量表示的稀疏问题 之前在看tf-idf代码时候思考了一个问题,不知道对于初学的大部分同学有没有这样一个疑惑,用tf-idf值构成的向量,维度可能跟词表的大小有关,那么对于一句话来说,这 ...
- C++智能指针使用说明
导读 STL提供四种智能指针:auto_ptr.unique_ptr.shared_ptr和weak_ptr.其中auto_ptr是C++98提供的解决方案,C++11以后均已摒弃.所有代码在gcc ...
- APC 篇——总结与提升
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...
- Swift可选类型
可选类型 可选类型的介绍 注意: 可选类型时swift中较理解的一个知识点 暂时先了解,多利用Xcode的提示来使用 随着学习的深入,慢慢理解其中的原理和好处 概念: 在OC开发中,如果一个变量暂停不 ...
- 为什么内部类调用的外部变量必须是final修饰的?
感谢原文:https://blog.csdn.net/u010393325/article/details/80643636 因为生命周期的原因.方法中的局部变量,方法结束后这个变量就要释放掉,fin ...
- Java定时器Timer使用方法详解
感谢大佬:https://www.jb51.net/article/129808.htm 一.概念 定时计划任务功能在Java中主要使用的就是Timer对象,它在内部使用多线程的方式进行处理,所以它和 ...