1、Parallel.Invoke 主要用于任务的并行
  这个函数的功能和Task有些相似,就是并发执行一系列任务,然后等待所有完成。和Task比起来,省略了Task.WaitAll这一步,自然也缺少了Task的相关管理功能。它有两种形式:
  Parallel.Invoke( params Action[] actions);
  Parallel.Invoke(Action[] actions,TaskManager manager,TaskCreationOptions options);

using System;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var actions = new Action[]
{
() => ActionTest("test 1"),
() => ActionTest("test 2"),
() => ActionTest("test 3"),
() => ActionTest("test 4")
}; Console.WriteLine("Parallel.Invoke 1 Test");
Parallel.Invoke(actions); Console.WriteLine("结束!");
} static void ActionTest(object value)
{
Console.WriteLine(">>> thread:{0}, value:{1}",
Thread.CurrentThread.ManagedThreadId, value);
}
}
}

Program

2、For方法,主要用于处理针对数组元素的并行操作(数据的并行)

using System;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
int[] nums = new int[] { , , , , , , , , , , , };
Parallel.For(, nums.Length, (i) =>
{
Console.WriteLine("针对数组索引{0}对应的那个元素{1}的一些工作代码……ThreadId={2}", i, nums[i], Thread.CurrentThread.ManagedThreadId);
});
Console.ReadKey();
}
}
}

Program

3、Foreach方法,主要用于处理泛型集合元素的并行操作(数据的并行)

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<int> nums = new List<int> { , , , , , , , , , , , };
Parallel.ForEach(nums, (item) =>
{
Console.WriteLine("针对集合元素{0}的一些工作代码……ThreadId={1}", item, Thread.CurrentThread.ManagedThreadId);
});
Console.ReadKey();
}
}
}

Program

  数据的并行的方式二(AsParallel()):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading; namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<int> nums = new List<int> { , , , , , , , , , , , };
var evenNumbers = nums.AsParallel().Select(item => Calculate(item));
//注意这里是个延迟加载,也就是不用集合的时候 这个Calculate里面的算法 是不会去运行 可以屏蔽下面的代码看效果;
Console.WriteLine(evenNumbers.Count());
//foreach (int item in evenNumbers)
// Console.WriteLine(item);
Console.ReadKey();
} static int Calculate(int number)
{
Console.WriteLine("针对集合元素{0}的一些工作代码……ThreadId={1}", number, Thread.CurrentThread.ManagedThreadId);
return number * ;
}
}
}

Program

  .AsOrdered() 对结果进行排序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleApp
{ class Program
{
static void Main(string[] args)
{
List<int> nums = new List<int> { , , , , , , , , , , , };
var evenNumbers = nums.AsParallel().AsOrdered().Select(item => Calculate(item));
//注意这里是个延迟加载,也就是不用集合的时候 这个Calculate里面的算法 是不会去运行 可以屏蔽下面的代码看效果;
//Console.WriteLine(evenNumbers.Count());
foreach (int item in evenNumbers)
Console.WriteLine(item);
Console.ReadKey();
} static int Calculate(int number)
{
Console.WriteLine("针对集合元素{0}的一些工作代码……ThreadId={1}", number, Thread.CurrentThread.ManagedThreadId);
return number * ;
}
}
}

Program

  ForEach的独到之处就是可以将数据进行分区,每一个小区内实现串行计算,分区采用Partitioner.Create实现。

using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading.Tasks; namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
for (int j = ; j < ; j++)
{
ConcurrentBag<int> bag = new ConcurrentBag<int>();
var watch = Stopwatch.StartNew();
watch.Start();
Parallel.ForEach(Partitioner.Create(, ), i =>
{
for (int m = i.Item1; m < i.Item2; m++)
{
bag.Add(m);
}
});
Console.WriteLine("并行计算:集合有:{0},总共耗时:{1}", bag.Count, watch.ElapsedMilliseconds);
GC.Collect(); }
}
}
}

Program

  ParallelOptions类
  ParallelOptions options = new ParallelOptions();
  //指定使用的硬件线程数为4
  options.MaxDegreeOfParallelism = 4;
  有时候我们的线程可能会跑遍所有的内核,为了提高其他应用程序的稳定性,就要限制参与的内核,正好ParallelOptions提供了MaxDegreeOfParallelism属性。

using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks; namespace ConsoleApp1
{
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public DateTime CreateTime { get; set; }
} class Program
{
static void Main(string[] args)
{
var dic = LoadData();
Stopwatch watch = new Stopwatch();
watch.Start();
var query2 = (from n in dic.Values.AsParallel()
where n.Age > && n.Age <
select n).ToList();
watch.Stop();
Console.WriteLine("并行计算耗费时间:{0}", watch.ElapsedMilliseconds); Console.Read();
} public static ConcurrentDictionary<int, Student> LoadData()
{
ConcurrentDictionary<int, Student> dic = new ConcurrentDictionary<int, Student>();
ParallelOptions options = new ParallelOptions();
//指定使用的硬件线程数为4
options.MaxDegreeOfParallelism = ;
//预加载1500w条记录
Parallel.For(, , options, (i) =>
{
var single = new Student()
{
ID = i,
Name = "hxc" + i,
Age = i % ,
CreateTime = DateTime.Now.AddSeconds(i)
};
dic.TryAdd(i, single);
}); return dic;
}
}
}

Program

常见问题的处理

  <1> 如何中途退出并行循环?
  是的,在串行代码中我们break一下就搞定了,但是并行就不是这么简单了,不过没关系,在并行循环的委托参数中提供了一个ParallelLoopState,该实例提供了Break和Stop方法来帮我们实现。
  Break: 当然这个是通知并行计算尽快的退出循环,比如并行计算正在迭代100,那么break后程序还会迭代所有小于100的。
  Stop:这个就不一样了,比如正在迭代100突然遇到stop,那它啥也不管了,直接退出。

using System;
using System.Collections.Concurrent;
using System.Threading.Tasks; namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
ConcurrentBag<int> bag = new ConcurrentBag<int>(); Parallel.For(, , (i, state) =>
{
if (bag.Count == )
{
//state.Break();
state.Stop();
return;
}
bag.Add(i);
}); Console.WriteLine("当前集合有{0}个元素。", bag.Count); }
}
}

Program

  取消(cancel)

using System;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleApp1
{
class Program
{
public static void Main()
{ var cts = new CancellationTokenSource();
var ct = cts.Token;
Task.Factory.StartNew(() => fun(ct));
Console.ReadKey();
//Thread.Sleep(3000);
cts.Cancel();
Console.WriteLine("任务取消了!"); } static void fun(CancellationToken token)
{
Parallel.For(, ,
new ParallelOptions { CancellationToken = token },
(i) =>
{
Console.WriteLine("针对数组索引{0}的一些工作代码……ThreadId={1}", i, Thread.CurrentThread.ManagedThreadId);
});
}
}
}

Program

  <2> 并行计算中抛出异常怎么处理?
  首先任务是并行计算的,处理过程中可能会产生n多的异常,那么如何来获取到这些异常呢?普通的Exception并不能获取到异常,然而为并行诞生的AggregateExcepation就可以获取到一组异常。

using System;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
try
{
Parallel.Invoke(Run1, Run2);
}
catch (AggregateException ex)
{
foreach (var single in ex.InnerExceptions)
{
Console.WriteLine(single.Message);
}
}
Console.WriteLine("结束了!");
//Console.Read();
} static void Run1()
{
Thread.Sleep();
throw new Exception("我是任务1抛出的异常");
} static void Run2()
{
Thread.Sleep();
throw new Exception("我是任务2抛出的异常");
}
}
}

Program

  注意Parallel里面 不建议抛出异常 因为在极端的情况下比如进去的第一批线程先都抛异常了 此时AggregateExcepation就只能捕获到这一批的错误,然后程序就结束了

using System;
using System.Collections.Generic;
using System.Threading.Tasks; namespace ConsoleApp1
{
public class TestClass
{
public static List<int> NumberList = null;
private static readonly object locker = new object();
public void Test(int Number)
{
throw new Exception("");
//lock (locker)
//{
// if (NumberList == null)
// {
// Console.WriteLine("执行添加");
// NumberList = new List<int>();
// NumberList.Add(1);
// //Thread.Sleep(1000);
// }
//}
//if (Number == 5 || Number == 7) throw new Exception(string.Format("NUmber{0}Boom!", Number));
//Console.WriteLine(Number);
}
} class Program
{
private static readonly object locker = new object();
static void Main(string[] args)
{
List<string> errList = new List<string>();
try
{
Parallel.For(, , (i) =>
{
try
{
TestClass a = new TestClass();
a.Test(i);
}
catch (Exception ex)
{
lock (locker)
{
errList.Add(ex.Message);
throw ex;
}
}
});
}
catch (AggregateException ex)
{
foreach (var single in ex.InnerExceptions)
{
Console.WriteLine(single.Message);
}
}
int Index = ;
foreach (string err in errList)
{
Console.WriteLine("{0}、的错误:{1}", Index++, err);
}
}
}
}

Program

  可以向下面这样来处理一下
  不在AggregateExcepation中来处理 而是在Parallel里面的try catch来记录错误,或处理错误

using System;
using System.Collections.Generic;
using System.Threading.Tasks; namespace ConsoleApp1
{
public class TestClass
{
public static List<int> NumberList = null;
private static readonly object locker = new object();
public void Test(int Number)
{
throw new Exception("");
//lock (locker)
//{
// if (NumberList == null)
// {
// Console.WriteLine("执行添加");
// NumberList = new List<int>();
// NumberList.Add(1);
// //Thread.Sleep(1000);
// }
//}
//if (Number == 5 || Number == 7) throw new Exception(string.Format("NUmber{0}Boom!", Number));
//Console.WriteLine(Number);
}
} class Program
{
private static readonly object locker = new object();
static void Main(string[] args)
{
List<string> errList = new List<string>();
Parallel.For(, , (i) =>
{
try
{
TestClass a = new TestClass();
a.Test(i);
}
catch (Exception ex)
{
lock (locker)
{
errList.Add(ex.Message);
}
//Console.WriteLine(ex.Message);
//注:这里不再将错误抛出.....
//throw ex;
}
}); int Index = ;
foreach (string err in errList)
{
Console.WriteLine("{0}、的错误:{1}", Index++, err);
}
}
}
}

Program

C# Parallel用法的更多相关文章

  1. Thread&ThreadPool、Parallel、Async和Await用法总结

    1.线程和线程池Thread&ThreadPool //线程初始化时执行方法可以带一个object参数,为了传入自定义参数,所以执行需单独调用用于传参. Console.WriteLine(& ...

  2. 异步方法的意义何在,Async和await以及Task的爱恨情仇,还有多线程那一家子。

    前两天刚感受了下泛型接口的in和out,昨天就开始感受神奇的异步方法Async/await,当然顺路也看了眼多线程那几个.其实多线程异步相关的类单个用法和理解都不算困难,但是异步方法Async/awa ...

  3. C# IEnumerable,Lambda表达式和 Parallel并行编程的用法

    以前一直主要做C++和C方面的项目,对C#不太了解熟悉,但听说不难,也就一直没有在意学习C#方面的知识.今天有个C#项目,需要做些应用的扩展,同时修改一些bug.但看了C#代码,顿时觉得有些不适应了. ...

  4. Task Parallel Library01,基本用法

    我们知道,每个应用程序就是一个进程,一个进程有多个线程.Task Parallel Library为我们的异步编程.多线程编程提供了强有力的支持,它允许一个主线程运行的同时,另外的一些线程或Task也 ...

  5. Thread、ThreadPool、Task、Parallel、Async和Await基本用法、区别以及弊端

    多线程的操作在程序中也是比较常见的,比如开启一个线程执行一些比较耗时的操作(IO操作),而主线程继续执行当前操作,不会造成主线程阻塞.线程又分为前台线程和后台线程,区别是:整个程序必须要运行完前台线程 ...

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

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

  7. Parallel并行之乱用

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

  8. C#基础系列——多线程的常见用法详解

    前言:前面几节分别介绍了下C#基础技术中的反射.特性.泛型.序列化.扩展方法.Linq to Xml等,这篇跟着来介绍下C#的另一基础技术的使用.最近项目有点紧张,所以准备也不是特别充分.此篇就主要从 ...

  9. xargs的原理剖析及用法详解

    转载请注明出处:http://www.cnblogs.com/f-ck-need-u/p/5925923.html 学习这个xargs花了很长时间,在网上翻了很久也查了很多书关于xargs的介绍,都只 ...

随机推荐

  1. Django积木块三——静态文件和上传文件

    静态文件和上传的文件 # 静态文件 STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), ) # ...

  2. CSU1333最短路问题SPFA

    fastvj.rainng.com/contest/236779#problem/I Description: n个点m条路每条路 l,r,t:表示这条路开l秒,关r秒,通过要t秒,问你车辆从s到t最 ...

  3. Reader和Writer

  4. 干货——详解Java中的关键字

    在平时编码中,我们可能只注意了这些static,final,volatile等关键字的使用,忽略了他们的细节,更深层次的意义. 本文总结了Java中所有常见的关键字以及一些例子. static 关键字 ...

  5. Java基础巩固——异常

    基础回顾 什么是异常? 在Java程序运行时,常常会出现一些非正常的现象,这种情况称为运行错误.根据其性质可以分为错误和异常. Java程序中所有抛出的异常都必须从Throwable派生而来.类Thr ...

  6. 脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?

    本文引用了公众号纯洁的微笑作者奎哥的技术文章,感谢原作者的分享. 1.前言   老于网络编程熟手来说,在测试和部署网络通信应用(比如IM聊天.实时音视频等)时,如果发现网络连接超时,第一时间想到的就是 ...

  7. Javascript高级编程学习笔记(79)—— 表单(7)选择框脚本

    选择框脚本 选择框由<option>和<select>元素创建,为了方便选择框的交互,除了提供表单字段的公有方法之外 HTMLSelectElement 类型还提供下列特有的属 ...

  8. OAuth2.0认证详解

    目录 什么是OAuth协议 OAuth2.0是为了解决什么问题? OAuth2.0成员和授权基本流程 OAuth2.0成员 OAuth2.0基本流程 什么是OAuth协议 OAuth 协议为用户资源的 ...

  9. Day3:html和css

    Day3:html和css 多类名选择器 样式的显示效果是跟html元素中的类名先后顺序无关,而是跟css样式的书写上下顺序有关. <!DOCTYPE html> <html lan ...

  10. ELK搭建elasticsearch常见报错

    问题一: [2018-01-31T16:27:21,712][WARN ][o.e.b.JNANatives ] unable to install syscall filter: Java.lang ...