Parallel类是对线程很好的一个抽象。该类位于System.Threading.Tasks名称空间中,提供了数据和任务并行性。
Parallel类定义了并行的for和foreach的静态方法。Parallel类使用多个任务,因此使用多个线程来完成这个作业。
Parallel.For()和Parallel.Foreach()方法在每次迭代中调用相同的代码,而Parallel.Invoke()方法允许同时调用不同的方法。Parallel.Invoke用于任务并行性,而Parallel.Foreach用于数据并行性。
下面的例子前面两个参数表示从0到9迭代。第三个参数是一个Action
ParallelLoopResult result = Parallel.For(0,10,i=> {
Console.WriteLine("{0},task:{1},thread:{2}",i,Task.CurrentId,Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(10);
});
上面的例子使用Task.Delay(10);可以看到不一样的结果,分析线程和任务是如何执行的
ParallelLoopResult result = Parallel.For(0,10,async i=> {
Console.WriteLine("{0},task:{1},thread:{2}",i,Task.CurrentId,Thread.CurrentThread.ManagedThreadId);
await Task.Delay(10);
Console.WriteLine("{0},task:{1},thread:{2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
});
Console.WriteLine("is completed:{0}", result.IsCompleted);
在输出中可以看到,调用 Task.Delay(10);后,线程发生了变化。任务不在存在,只留下线程,而且重用了前面的线程,还有一个重要的方面是,Parallel类的For方法并没有等待延迟,而是直接完成。它只等待它创建的任务,而不等待其他后台活动。
提前停止Parallel.For
可以提前终止所有迭代,调用ParallelLoopState的Break和Stop方法。如下:
ParallelLoopResult result = Parallel.For(10, 30, async (int i ,ParallelLoopState pls) => {
Console.WriteLine("{0},task:{1}", i, Task.CurrentId);
await Task.Delay(10);
if (i > 13)
pls.Break();
});
Console.WriteLine("is completed:{0}", result.IsCompleted);
Console.WriteLine("lowest break iteration:{0}",result.LowestBreakIteration);
Parallel.ForEach方法遍历是已异步方式遍历,没有确定遍历顺序。此方法的中断也For方法相同。
string[] data = { "1","2","3","4","5",};
ParallelLoopResult result = Parallel.ForEach<string>(data, s => { Console.WriteLine(s); });
Parallle.Invoke方法允许传递一个Action委托数组,也就是可以并行调用多个方法。
static void Main()
{
Parallel.Invoke(Foo, Bar);
}
static void Foo()
{
Console.WriteLine(1);
}
static void Bar()
{
Console.WriteLine(2);
}