[转载]Net 4.0 Parallel 编程 -Task

http://www.cnblogs.com/Henllyee/archive/2011/06/06/net_parallel_programing.html

 

http://www.cnblogs.com/dajiang02/archive/2012/02/08/2342198.html

 

 

在上篇文章中我们看过了如何创建Task,本篇文章就各种类型Task的使用进行说明。


 

Task Continuations


 

首先我们来看看延续的Task,所谓的延续的Task就是在第一个Task完成后自动启动下一个Task。我们通过ContinueWith方法来创建延续的Task。我们假设有一个接受xml解析的服务,首先从某个地方接受文件,然后解析入库,最后返回回执是否解析正确:


 









1

2

3

4

5

6

7

8

9


[TestMethod]

public void TaskParallelPrint()

{

    var ReceiveTask =
new Task(() => ReceiveXml());

    var ResolveTask =
ReceiveTask.ContinueWith<
bool>((r) =>
ResolveXml());

    var SendFeedBackTask
= ResolveTask.ContinueWith<
string>((s) =>
SendFeedBack(s.Result));

    ReceiveTask.Start();

    Console.WriteLine(SendFeedBackTask.Result);

}


 

在每次调用ContinueWith方法时,每次会把上次Task的引用传入进来,以便检测上次Task的状态,比如我们可以使用上次Task的Result属性来获取返回值。上面的代买我们也可以这么写:


 









1

2

3

4

5

6

7

8


[TestMethod]

public void TaskParallelPrint()

{

    var SendFeedBackTask
= Task.Factory.StartNew(() => ReceiveXml())

                            .ContinueWith<bool>(s =>
ResolveXml())

                            .ContinueWith<string>(r =>
SendFeedBack(r.Result));

    Console.WriteLine(SendFeedBackTask.Result);

}


 

Detached Nested Tasks


 

有些情况下我们需要创建嵌套的Task,嵌套里面又分为分离的和不分离的。其创建的方式很简单,就是在Task的body里面创建一个新的Task。如果新的Task未指定AttachedToParent选项,那么就是分离嵌套的。我们看下面这段代码:


 









1

2

3

4

5

6

7

8

9

10

11

12


var outTask =
Task.Factory.StartNew(() =>

{

    Console.WriteLine("Outer task beginning...");

    var childTask =
Task.Factory.StartNew(() =>

    {

        Thread.SpinWait(3000000);

        Console.WriteLine("Detached nested task completed.");

    });

});

outTask.Wait();

Console.WriteLine("Outer task completed.");

Console.ReadKey();


 

我们可以看到运行结果是:


 

image


 

上面的代码中outTask.Wait()表示等待outTask执行完成。


 

Child Tasks


 

我们将上面的代码加上TaskCreationOptions选项:


 









1

2

3

4

5

6

7

8

9

10

11

12


var outTask =
Task.Factory.StartNew(() =>

{

    Console.WriteLine("Outer task beginning...");

    var childTask =
Task.Factory.StartNew(() =>

    {

        Thread.SpinWait(3000000);

        Console.WriteLine("Detached nested task completed.");

    },TaskCreationOptions.AttachedToParent);

});

outTask.Wait();

Console.WriteLine("Outer task completed.");

Console.ReadKey();


 

看到运行结果:


 

image


 

Cancellation Task


 

如何取消一个Task呢,我们通过cancellation的tokens来取消一个Task。在很多Task的Body里面包含循环,我们可以在轮询的时候判断IsCancellationRequested属性是否为True,如果是True的话,就可以停止循环以及释放资源,同时抛出OperationCanceledException异常出来。来看一段示例代码:


 









1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32


var tokenSource
=
new
CancellationTokenSource();

var token =
tokenSource.Token;

var task =
Task.Factory.StartNew(() =>

{

    for (var i = 0; i <
10000000; i++)

    {

        if (token.IsCancellationRequested)

        {

            Console.WriteLine("Task cacel started...");

            throw new OperationCanceledException(token);

        }

        

    }

},token);

token.Register(() =>

{

    Console.WriteLine("Canceled");

});

Console.WriteLine("Press enter again to cancel task");

Console.ReadKey();

tokenSource.Cancel();

try

{

    task.Wait();

}

catch (AggregateException
e)

{

    foreach (var v
in e.InnerExceptions)

        Console.WriteLine("msg: " + v.Message);


}

Console.ReadKey();

 

 

posted @ 2012-03-02 12:09  火腿骑士  阅读(201)  评论(0编辑  收藏  举报