C#4.0入门 第三章 Task类与PLINQ—第二页 PLINQ(转)

Task类相关的时间点


Task类可以被用来执行多个处理。这个时候,想知道的时间点一般有两个。一个是单独一个任务结束的时刻。还有一个是全部任务结束的时刻。这两个时间点可以很容易地被确定。



Task.WaitAny方法与Task.WaitAll方法的参数是一个或多个Task对象。这两个方法的功能分别为返回单个任务结束的时刻与返回所有任务结束的时刻。使用这两个方法,可以很简单的书写代码来创建多个任务并等待它们结束的时刻。


task3.cs



 using System;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
var task1 = Task.Factory.StartNew(() =>
{
for (int i = 0; i < 100; i++) Console.Write('A');
});
var task2 = Task.Factory.StartNew(() =>
{
for (int i = 0; i < 200; i++) Console.Write('B');
});
var task3 = Task.Factory.StartNew(() =>
{
for (int i = 0; i < 300; i++) Console.Write('C');
});
Task.WaitAny(task1, task2, task3);
Console.WriteLine();
Console.WriteLine("stopped one task");
Task.WaitAll(task1, task2, task3);
Console.WriteLine();
Console.WriteLine("stopped all tasks");
}
}


运行结果(结果因环境与时序而异)




 ABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
stopped one task
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBB
stopped all task


那么,这里有一个问题。Task.WaitAny方法与Task.WaitAll方法虽然使用起来很方便,对于task相互之间关系的控制功能没有线程相互之间关系的控制功能那么强。不管变得多么简单,同步的问题还是完全存在的。要竞争使用别的类正在使用的资源的话,毕竟还是要必须使用lock语句的。那么,这样的话到底是否应该使用任务?


答案是“应该要使用”。“无障碍的很方便的使用”这正是Task类的特性。使用Task类是对于多核时代的对应方法之一。虽然还是存在同步问题,但是在多核时代已变成不是问题或小到可以忽略的问题了。相反的,养成把并行处理考虑成分散给几个任务来处理的习惯才是比较重要的。这是一种能够充分使用未来型的多核CPU的强大力量的方法。

PLINQ(Parallel
Linq)


虽然PLINQ是时下关于并行处理的热门话题,但是它的使用方法是非常简单的。


下例为创建包含查询表达式的简单代码。程序本身没有什么太大意义,只不过是找出“2”,然后输出。


创建包含查询表达式的简单代码



 
using System;
using System.Linq;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
int[] ar = { 1, 2, 3 };
var q1 = from n in ar
where n == 2
select n;
foreach (var n in q1)
Console.WriteLine("found {0}", n);
}
}


运行结果




 found 2


如果把上例改成用并行处理,只要在查询表达式中追加AsParallel方法就可以了。


把上例改成用并行处理



 
var q1 = from n in ar.AsParallel()
where n == 2
select n;


method形式也是一样。例如下面这个查询表达式。


method形式的查询表达式



 
var q1 = ar.Where((c) => c == 2);


象下例那样,在方法链的开头插入AsParallel方法就可以了。


把上例改成用并行处理



 
var q1 = ar.AsParallel().Where((c) => c == 2);


从上面两个例子可以知道,使用PLINQ是十分简单的,只要用一个方法就可以用并行来处理查询表达式了。但是,如果说这样做百分之百会给性能带来好处,倒也未必。因为,存在如下情况。

1.对别的服务器使用查询表达式进行查询的时候,使用PLINQ不一定会给性能带来多大好处(因为不属于本地并行处理的范畴了。PLINQ是主要用来进行本地端Linq
to Objects的处理的,对于Linq to SQL的处理不一定有效)

2.在大量使用查询表达式的时候,并不是每一句查询表达式都是性能瓶颈的关键,如果每一个查询表达式都插入AsParallel方法,不会带来太大好处,在浪费时间的同时,代码的可读性也降低了。

3.插入AsParallel方法后,有时结果会发生变化。

重要的问题是最后一个。到底会发生什么变化?下一页中进行回答。
posted @ 2011-06-11 16:03  董雨  阅读(293)  评论(0编辑  收藏  举报