【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")
);

 



posted @ 2022-02-17 16:55  小林野夫  阅读(126)  评论(0编辑  收藏  举报
原文链接:https://www.cnblogs.com/cdaniu/