您的位置:首页 > 编程语言 > C#

NET 4.0 - C# 4.0 新特性之并行运算(Parallel)

2011-07-03 15:18 507 查看
C# 4.0 的新特性之并行运算

Parallel.For - for 循环的并行运算
Parallel.ForEach - foreach 循环的并行运算
Parallel.Invoke - 并行调用多个任务
Task - 任务,基于线程池。其使我们对并行编程变得更简单,且不用关心底层是怎么实现的
PLINQ - 用于对内存中的数据做并行运算,也就是说其只支持 LINQ to Object 的并行运算

示例

1、Parallel.For 的 Demo

Parallel/ParallelFor.aspx.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

namespace CSharp.Parallel

{

public partial
class ParallelFor : System.Web.UI.Page

{

void Page_Load() void Page_Load(object sender, EventArgs e)

{

Normal();

ParallelForDemo();

}

void Normal() void Normal()

{

DateTime dt = DateTime.Now;

for (int i = 0; i < 20; i++)

{

GetData(i);

}

Response.Write((DateTime.Now - dt).TotalMilliseconds.ToString());

Response.Write("<br />");

Response.Write("<br />");

}

void ParallelForDemo() void ParallelForDemo()

{

DateTime dt = DateTime.Now;

// System.Threading.Tasks.Parallel.For -
for 循环的并行运算

System.Threading.Tasks.Parallel.For(0, 20, (i) => { GetData(i); });

Response.Write((DateTime.Now - dt).TotalMilliseconds.ToString());

Response.Write("<br />");

}

int GetData() int GetData(int i)

{

System.Threading.Thread.Sleep(100);

Response.Write(i.ToString());

Response.Write("<br />");

return i;

}

}

}

/*

运行结果:

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

2000.0514

0

13

1

19

7

12

18

6

2

8

10

14

4

16

5

3

15

17

9

11

300.0077

*/

2、Parallel.ForEach 的 Demo

Parallel/ParallelForEach.aspx.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

namespace CSharp.Parallel

{

public partial
class ParallelForEach : System.Web.UI.Page

{

List<int> _data = new List<int>() List<int> _data =
new List<int>();

void Page_Load() void Page_Load(object sender, EventArgs e)

{

InitData();

Normal();

ParallelForEachDemo();

}

void InitData() void InitData()

{

_data.Clear();

for (int i = 0; i < 20; i++)

{

_data.Add(i);

}

}

void Normal() void Normal()

{

DateTime dt = DateTime.Now;

for (int i = 0; i < 20; i++)

{

GetData(i);

}

Response.Write((DateTime.Now - dt).TotalMilliseconds.ToString());

Response.Write("<br />");

Response.Write("<br />");

}

void ParallelForEachDemo() void ParallelForEachDemo()

{

DateTime dt = DateTime.Now;

// System.Threading.Tasks.Parallel.ForEach - foreach 循环的并行运算

System.Threading.Tasks.Parallel.ForEach(_data, (index) => { GetData(index); });

Response.Write((DateTime.Now - dt).TotalMilliseconds.ToString());

Response.Write("<br />");

}

int GetData() int GetData(int i)

{

System.Threading.Thread.Sleep(100);

Response.Write(i.ToString());

Response.Write("<br />");

return i;

}

}

}

/*

运行结果:

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

2000.0514

0

6

12

18

1

2

7

13

19

4

3

8

14

9

5

15

10

16

11

17

600.0154

*/

3、Parallel.Invoke 的 Demo

Parallel/ParallelInvoke.aspx.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Threading;

namespace CSharp.Parallel

{

public partial
class ParallelInvoke : System.Web.UI.Page

{

void Page_Load() void Page_Load(object sender, EventArgs e)

{

var tasks = new Action[] { () => Task1(), () => Task2(), () => Task3() };

// System.Threading.Tasks.Parallel.Invoke - 并行调用多个任务

System.Threading.Tasks.Parallel.Invoke(tasks);

}

void Task1() void Task1()

{

Thread.Sleep(3000);

Response.Write("Task1 - " +
"ThreadId:" + Thread.CurrentThread.ManagedThreadId.ToString() +
" - " + DateTime.Now.ToString("HH:mm:ss"));

Response.Write("<br />");

}

void Task2() void Task2()

{

System.Threading.Thread.Sleep(3000);

Response.Write("Task2 - " +
"ThreadId:" + Thread.CurrentThread.ManagedThreadId.ToString() +
" - " + DateTime.Now.ToString("HH:mm:ss"));

Response.Write("<br />");

}

void Task3() void Task3()

{

System.Threading.Thread.Sleep(3000);

Response.Write("Task3 - " +
"ThreadId:" + Thread.CurrentThread.ManagedThreadId.ToString() +
" - " + DateTime.Now.ToString("HH:mm:ss"));

Response.Write("<br />");

}

}

}

/*

运行结果:

Task2 - ThreadId:26 - 09:11:58

Task1 - ThreadId:25 - 09:11:58

Task3 - ThreadId:24 - 09:11:58

*/

4、Task 的 Demo

Parallel/ParallelTask.aspx.cs

/*

Task - 任务,基于线程池。其使我们对并行编程变得更简单,且不用关心底层是怎么实现的

*/

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Threading;

using System.Threading.Tasks;

namespace CSharp.Parallel

{

public partial
class ParallelTask : System.Web.UI.Page

{

void Page_Load() void Page_Load(object sender, EventArgs e)

{

/*

* CancellationTokenSource - 取消任务的操作需要用到的一个类

* Token - 一个 CancellationToken 类型的对象,用于通知取消指定的操作

* IsCancellationRequested - 是否收到了取消操作的请求

* Cancel() - 结束任务的执行

* ParallelOptions - 并行运算选项

* CancellationToken - 设置一个 Token,用于取消任务时的相关操作

* MaxDegreeOfParallelism - 指定一个并行循环最多可以使用多少个线程

*/

CancellationTokenSource cts =
new CancellationTokenSource();

ParallelOptions pOption = new ParallelOptions() { CancellationToken = cts.Token };

pOption.MaxDegreeOfParallelism = 10;

Response.Write("开始执行,3.5 秒后结束");

Response.Write("<br />");

/*

* Task - 任务类

* Factory.StartNew() - 创建并开始一个或一批新任务

* ContinueWith() - 此任务完成后执行指定的另一个任务

* AsyncState - 此任务的上下文对象

* Wait() - 阻塞,直到任务完成

*/

Task task0 = Task.Factory.StartNew(() =>

{

Thread.Sleep(3500);

cts.Cancel();

Response.Write("结束");

Response.Write("<br />");

});

// 通过 System.Threading.Tasks.Parallel.Invoke 执行任务的时候,可以加入 ParallelOptions 参数,用于对此并行运算做一些配置

System.Threading.Tasks.Parallel.Invoke(pOption,

() => Task1(pOption.CancellationToken),

() => Task2(pOption.CancellationToken));

/*

* 一个 Task 内可以包含多个 Task

Task tasks = new Task(() =>

{

Task.Factory.StartNew(() => Method());

Task.Factory.StartNew(() => Method2());

Task.Factory.StartNew(() => Method3());

});

tasks.Start();

// 阻塞,直到整个任务完成

tasks.Wait();

*/

/*

* 带返回值的 Task

Func<object, long> fun = delegate(object state)

{

return 1.0;

};

Task<long> tsk = new Task<long>(fun,
"state");

tsk.Start();

Response.Write(tsk.Result.ToString());

*/

}

void Task1() void Task1(CancellationToken token)

{

// 每隔 1 秒执行一次,直到此任务收到了取消的请求

// 注意:虽然此处是其他线程要向主线程(UI线程)上输出信息,但因为使用了 Task ,所以不用做任何处理

while (!token.IsCancellationRequested)

{

Response.Write("Task1 - " +
"ThreadId: " + Thread.CurrentThread.ManagedThreadId.ToString());

Response.Write("<br />");

Thread.Sleep(1000);

}

}

void Task2() void Task2(CancellationToken token)

{

while (!token.IsCancellationRequested)

{

Response.Write("Task2 - " +
"ThreadId: " + Thread.CurrentThread.ManagedThreadId.ToString());

Response.Write("<br />");

Thread.Sleep(1000);

}

}

}

}

/*

运行结果:

开始执行,3.5 秒后结束

Task2 - ThreadId: 6

Task1 - ThreadId: 48

Task1 - ThreadId: 48

Task2 - ThreadId: 6

Task2 - ThreadId: 6

Task1 - ThreadId: 48

Task2 - ThreadId: 6

Task1 - ThreadId: 48

结束

*/

5、PLINQ 的 Demo

Parallel/ParallelPLINQ.aspx.cs

/*

PLINQ - 用于对内存中的数据做并行运算,也就是说其只支持 LINQ to Object 的并行运算

*/

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

namespace CSharp.Parallel

{

public partial
class ParallelPLINQ : System.Web.UI.Page

{

void Page_Load() void Page_Load(object sender, EventArgs e)

{

List<int> list = new List<int>();

for (int i = 0; i < 100; i++)

{

list.Add(i);

}

// AsParallel() - 并行运算

// AsSequential() - 串行运算

// AsOrdered() - 保持数据的原有顺序(AsSequential()指的是串行运算;AsOrdered()指的是如果在并行运算的前提下,它会把结果先缓存,然后排序,最后再把排序后的数据做输出)

// AsUnordered() - 可以不必保持数据的原有顺序

// WithDegreeOfParallelism() - 明确地指出需要使用多少个线程来完成工作

// WithCancellation(new CancellationTokenSource().Token) - 指定一个 CancellationToken 类型的参数

ParallelQuery nums = from num
in list.AsParallel<int>().AsOrdered<int>()

where num % 10 == 0

select num;

foreach (var num in nums)

{

Response.Write(num.ToString());

Response.Write("<br />");

}

// 聚合方法也可以做并行运算

Response.Write(list.AsParallel().Average().ToString());

Response.Write("<br />");

// 自定义聚合方法做并行运算的 Demo(实现一个取集合的平均值的功能)

double myAggregateResult = list.AsParallel().Aggregate(

// 聚合变量的初始值

0d,

// 在每个数据分区上,计算此分区上的数据

// 第一个参数:对应的数据分区的计算结果;第二个参数:对应的数据分区的每个数据项

(value, item) =>

{

double result = value + item;

return result;

},

// 根据每个数据分区上的计算结果,再次做计算

// 第一个参数:全部数据的计算结果;第二个参数:每个数据分区上的计算结果

(value, data) =>

{

double result = value + data;

return result;

},

// 根据全部数据的计算结果再次计算,得到最终的聚合结果

(result) => result / list.Count

);

Response.Write(myAggregateResult.ToString());

}

}

}

/*

运行结果:

0

10

20

30

40

50

60

70

80

90

49.5

49.5

*/

binbin88.taobao.com

QQ: 25548016
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: