Task并行封装

一:Task中并行和串行

串行:

for (int i = 0; i < 100; i++)
{
    Console.WriteLine(i);
}

1572968795179

并行:

1
2
3
4
Parallel.For(0, 100, (item) =>
{
Console.WriteLine(item);
});

1572968878768

二:Parallel.For的实现结构

1.可以设置指定的线程计算,不需要所有的线程参与计算。

1
int nNumExpectedWorkers = (parallelOptions.EffectiveMaxConcurrencyLevel == -1) ? PlatformHelper.ProcessorCount : parallelOptions.EffectiveMaxConcurrencyLevel;

2.分区函数,实现线程并行

1
RangeManager rangeManager = new RangeManager((long)fromInclusive,(long)toExclusive, 1L, nNumExpectedWorkers);

分区后,使用 ParallelForReplicatingTask处理线程,这个类继承Task

3.不要在Parallel.For中使用break()或Stop(),或许会给你引入不必要的bug;

ConcurrentStack<int> stack = new ConcurrentStack<int>();
      Parallel.For(0, 100, (item,loop) =>
      {
          Thread.Sleep(100000);
          stack.Push(item);
      });
      Console.WriteLine(string.Join(",", stack));

1573015947294

线程池中开启16个线程,使用了12个线程,还有4个线程是CLR为发生饱和,做备用线程

三.Parallel.For高级重载

Parallel.For解决问题是数组的遍历。

public static ParallelLoopResult For(int fromInclusive, int toExclusive, Func localInit, Func<int, ParallelLoopState, TLocal, TLocal> body, Action localFinally)

计算1-100的总和

var totalNums = 0;
       Parallel.For(1,100,()=> {
           return 0;
       },(current,loop,total)=> {
           total += (int)current;
           return total;
       },(total)=> {
           Interlocked.Add(ref totalNums,total);
       });
       Console.WriteLine(totalNums);

结果4950

四:Parallel.Foreach()

Parallel.Foreach()应对一些集合运算【非数组】

Dictionary<int, int> dic = new Dictionary<int, int>() { 
{ 1, 100 }, { 2, 200 }, { 3, 300 } };
       Parallel.ForEach(dic,(item)=> {
            Console.WriteLine(item.Key+":"+item.Value);
        });

1573048308181

1573048681375

上面是源码,分区函数,首先得分区。

五:Parallel.Invoke()

Parallel.Invoke(() =>
{
    Console.WriteLine("我是并行计算{0}",Thread.CurrentThread.ManagedThreadId);
}, () =>
{
    Console.WriteLine("我是并行计算{0}", Thread.CurrentThread.ManagedThreadId);
}, () =>
{
    Console.WriteLine("我是并行计算{0}", Thread.CurrentThread.ManagedThreadId);
});

1573049137151

Parallel.Invoke()可以同时开始多个线程并行执行,CPU回分配不同的线程执行任务。