1、Parallel并发执行
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
using System.Configuration;
using System.Collections.Concurrent;
namespace ConsoleApplication57
{
class Program
{
static void Main(string[] args)
{
ParallelDemo BingFa = new ParallelDemo();
BingFa.ParallelInvokemethod();
Console.ReadKey();
BingFa.ParallelForMethod();
Console.ReadKey();
BingFa.ParallelForMethod2();
BingFa.ParallelBreak();
}
}
public class ParallelDemo {
private Stopwatch stopWatch = new Stopwatch();
public void Run1() {
Thread.Sleep(2000);
Console.WriteLine("Task 1 is cost 2 sec");
}
public void Run2() {
Thread.Sleep(3000);
Console.WriteLine("Task 2 is cost 3 sec");
}
public void ParallelInvokemethod() {
stopWatch.Start();
Parallel.Invoke(Run1, Run2);
stopWatch.Stop();
Console.WriteLine("Parallel run" + stopWatch.ElapsedMilliseconds + "ms");
stopWatch.Restart();
Run1();
Run2();
stopWatch.Stop();
Console.WriteLine("Normall run"+stopWatch.ElapsedMilliseconds+"ms");
}
public void ParallelForMethod() {
stopWatch.Start();
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 60000; j++) {
int sum = 0;
sum += i;
}
}
stopWatch.Stop();
Console.WriteLine("Normalfor run" + stopWatch.ElapsedMilliseconds + "ms");
stopWatch.Reset();
stopWatch.Start();
Parallel.For(0, 10000, item =>
{
for (int j = 0; j < 60000; j++)
{
int sum = 0;
sum += item;
}
});
stopWatch.Stop();
Console.WriteLine("ParallelFor run" + stopWatch.ElapsedMilliseconds + "ms");
}
public void ParallelForMethod2() {
var obj = new Object();
long num = 0;
ConcurrentBag<long> bag = new ConcurrentBag<long>();
stopWatch.Start();
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 60000; j++)
{
num++;
}
}
stopWatch.Stop();
Console.WriteLine("NormalFor run"+stopWatch.ElapsedMilliseconds+"ms");
stopWatch.Reset();
stopWatch.Start();
Parallel.For(0,10000,item=>{
for(int j=0;j<60000;j++){
lock(obj){
num++;
}}});
stopWatch.Stop();
Console.WriteLine("ParallelFor run"+stopWatch.ElapsedMilliseconds+"ms");
Console.ReadKey();
}
public void ParallelBreak()
{
ConcurrentBag<int> bag = new ConcurrentBag<int>();
stopWatch.Start();
Parallel.For(0, 1000, (i, state) =>
{
if (bag.Count == 300)
{
state.Stop();
return;
}
bag.Add(i);
});
stopWatch.Stop();
Console.WriteLine("Bag count is {}{}", bag.Count, stopWatch.ElapsedMilliseconds+"ms");
}
//</long></long>
}
//public void ParallelForMethod{
//}
}
2 、使用Parallel来做循环
Parallel.For(0,100,i=>{
Console.writeLine(i+" ");
}); #######从零到99,运行或输出的顺序不对,但是使用for循环的,并行执行的时候会初夏输出顺序不同的问题。
Parallel.Foreach和foreach很类似,
List<int> list=new List<int>();
list.Add(0);
Parallel.ForEach(list,item=>{
DoWork(item);
});
3、异常处理
由于执行的任务是并发的执行的,产生的异常回是多个,简单的Exception不能获取异常,使用AggregateException课可以捕获到一组异常
Task pt = new Task(() => { Task.Factory .StartNew(() => { throw new Exception("ex 1"); }, TaskCreationOptions.AttachedToParent); Task.Factory .StartNew(() => { Task.Factory .StartNew(() => { throw new Exception("ex 2-1"); }, TaskCreationOptions.AttachedToParent); throw new Exception("ex 2"); }, TaskCreationOptions.AttachedToParent); throw new Exception("ex 3"); });
pt.Start()开始任务,异常不会抛出,但必须被处理,以下是若干种方法。
//方法1: pt.ContinueWith(t => { t.Exception.Handle(ex => { Console.WriteLine(ex.Message); return true; }); }, TaskContinuationOptions.OnlyOnFaulted);
//方法2: pt.ContinueWith(t => { t.Exception.Handle(ex => { Console.WriteLine(ex.GetBaseException().Message); return true; }); }, TaskContinuationOptions.OnlyOnFaulted);
//方法3: pt.ContinueWith(t => { foreach (var ex in t.Exception.Flatten().InnerExceptions) { Console.WriteLine(ex.Message); } }, TaskContinuationOptions.OnlyOnFaulted);
//方法4: pt.ContinueWith(t => { foreach (var ex in t.Exception.InnerExceptions) { Console.WriteLine(ex.Message); } }, TaskContinuationOptions.OnlyOnFaulted);
5、线程并行安全,如下执行的时候输出错误,这是因为List是非线程安全集合,所有的线程都可以修改他的值,造成线程的安全问题。
---------- namespace ConsoleApplication58
{
class Program
{
static void Main(string[] args)
{
PEnumberable Test = new PEnumberable();
Test.ListWithpallel();
Console.ReadKey();
}
}
public class PEnumberable {
public void ListWithpallel() {
List<int> list = new List<int>();
Parallel.For(0, 1000, item =>
{
list.Add(item);
});
Console.WriteLine("list count is{0}",list.Count());
} }}
################
使用system.Collection.Concurrent, 实例ConcurrentBag泛型集合
public void ConcurrentBagwithPallel() {
ConcurrentBag<int> list = new ConcurrentBag<int>();
Parallel.For(0, 10000, item =>
{
list.Add(item);
});
Console.WriteLine("ConcurrentBag's count is{0}", list.Count());
}
现在我们看看 ConcurrentBag中的数据是怎么排列的
public void ConcurrentBagwithPallel() {
ConcurrentBag<int> list = new ConcurrentBag<int>();
Parallel.For(0, 10000, item =>
{
list.Add(item);
});
Console.WriteLine("ConcurrentBag's count is{0}", list.Count());
int n = 0;
foreach (int i in list) {
if (n > 10)
break;
n++; Console.WriteLine("Item{0}={1}", n, i);
}
Console.WriteLine("ConcurrentBag's max item is{0]", list.Max());
}
从上面的执行可窥看出ConcurentBag中的数据排序是乱序的,但是属性Max ,Frist ,Last等都可以使用,关于线程安全的问题还用 Dictionary 的ConcurrentDictionary还用 ConcurrentStack,ConcurrentQueue等
6、Parallel Linq 的用法