码迷,mamicode.com
首页 > 其他好文 > 详细

TPL Part 1 Task 的使用

时间:2015-04-18 13:08:52      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:

创建Task

//1. 使用Action
Task task1 = new Task(newAction(printMessage));
// 使用匿名代理
Task task2 = new Task(delegate {
printMessage();
});
// 使用Lambda
Task task3 = new Task(() =>printMessage());
// 使用匿名代理
Task task4 = new Task(() => {
printMessage();
});


 

还可以使用Factory.StartNew()创建Task,区别在于, Factory.StartNew()主要用于创建简单的,生命周期短的Task。无法Start()已经运行的Task,必须创建1个新Task实例然后Start。

同时运行多个Task,Task Scheduler来决定线程的分配以及Task运行时的顺序。

 

设置Task参数

    Task task1 = newTask((msg)=>{
    Console.WriteLine(msg);
    },
"Firsttask");
task1.Start();
Console.ReadLine();


传参,打印。

 

获取Task返回值

Task<int> task1 = new Task<int>(()=> {
Thread.Sleep(3000);
return 1;
});
task1.Start();
Console.WriteLine("Result 1: {0}", task1.Result); //Threadblocked
 
Task<int> task2 = new Task<int>(obj=> {
Thread.Sleep(3000);
return 2;
}, 100);
task2.Start();
Console.WriteLine("Result 2: {0}", task2.Result);
Console.ReadLine();


在获取Task的Result时,会造成线程阻塞,对于上例来说,task1执行完毕时,Task2才开始执行。

取消Task

 

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
Task task = new Task(() => {
for(int i = 0;i < 5; i++) {
Thread.Sleep(1000);
if(token.IsCancellationRequested) {
Console.WriteLine("Task cancel detected");
throw new OperationCanceledException(token);
} else{
Console.WriteLine("Int value {0}", i);
}
}
},token);
task.Start();
Console.WriteLine("Task started , Press enter to cancel task");
Console.ReadLine();
Console.WriteLine("Cancelling task");
tokenSource.Cancel();


先创建了1个TokenSource,将其中的Token传入Action中,在Action中每秒打印1个数字,直到取消Task时,打印并抛出OperationCaceledException。

对于多个Task的情形,还可以将同一个Token传入它们,就可以一次取消多个Task。

 

监控Task

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
 
Task task1 = new Task(() => {
for(int i = 0;i < 5; i++) {
if(token.IsCancellationRequested) {
Console.WriteLine("Task cancel detected");
throw new OperationCanceledException(token);
} else{
Console.WriteLine("Int value {0}", i);
}
 
Thread.Sleep(1000);
}
},token);
task1.Start();
Console.WriteLine("Task1 started , Press enter to cancel task");
 
Task task2 = new Task(()=>{
Console.WriteLine("task2 : waiting for task 1 , maximum wait 3 seconds");
token.WaitHandle.WaitOne(3000);
Console.WriteLine("execute task2");
});
task2.Start();
 
Console.ReadLine();
Console.WriteLine("Cancelling task");
tokenSource.Cancel();


在上例中,开启了两个Task,task2需要等待task1执行完毕或被取消才执行,最大等待时间为3秒。

组合取消Task

对于一些情形,会希望传递多个Token的组合,当任意1个Token 取消了Task,就执行取消:

CancellationTokenSource tokenSource1 = new CancellationTokenSource();
CancellationTokenSource tokenSource2 = new CancellationTokenSource();
CancellationTokenSource tokenSource3 = new CancellationTokenSource();
 
CancellationTokenSource compositeSource =
CancellationTokenSource.CreateLinkedTokenSource(
tokenSource1.Token,tokenSource2.Token, tokenSource3.Token);
 
Task task = new Task(() => {
Console.WriteLine("any 1 of 3 token canceled , it will cancel");
compositeSource.Token.WaitHandle.WaitOne();
Console.WriteLine("task canceled");
 
throw new OperationCanceledException(compositeSource.Token);
},compositeSource.Token);
task.Start();
Console.WriteLine("task started and waiting for cancel");
 
Thread.Sleep(1000);
Console.WriteLine("token2 canceling");
tokenSource2.Cancel();
 
Console.ReadLine();


如上例代码所示,3个Token的组合被传入Task中,当Token2取消时,Task被取消,还可以将Token2改为Token1和Token3,不再一一演示。

如果需要在程序外部了解Task是否被Cancel,只需访问IsCanceled属性即可。

等待Task

有时需要在Task外部等待Task执行完毕,可以使用task.Wait()。以下为示例场景:

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationTokentoken = tokenSource.Token;
 
Task task = new Task(()=>{
Console.WriteLine("task : please wait me for 3 secs to complete in main thread");
for(var i = 0 ;i < 3; i++){
Thread.Sleep(1000);
}
Console.WriteLine("task: complete");
 
},token);
task.Start();
 
Console.WriteLine("main thread: i do some other jobs...");
Thread.Sleep(1000);
Console.WriteLine("main thread: i am ready to wait...");
task.Wait(1500);
 
Console.WriteLine("main thread : i continue some other job...");


如上例所示,在Task要求主线程等待3秒,可在主线程中,最多只能等1.5秒,如果task没结束就直接继续主线程中任务的执行。

等待多个任务

在主线程中,需要等待多个线程都执行完毕的情况:

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
 
Task task1 = new Task(()=>{
Console.WriteLine("task1 : wait me , main thread");
for(vari = 0 ;i < 3; i++){
Console.WriteLine(string.Format("task1 : {0}/3  done",i+1));
Thread.Sleep(1000);
 
}
Console.WriteLine("task1: complete");
 
},token);
task1.Start();
 
Task task2 = new Task(()=>{
Console.WriteLine("task2 : wait me , main thread");
for(var i = 0 ;i < 2; i++){
Console.WriteLine(string.Format("task2 : {0}/2  done",i+1));
Thread.Sleep(1000);
}
Console.WriteLine("task2: complete");
 
},token);
task2.Start();
 
Console.WriteLine("main thread : waiting for task1 and task2");
Task.WaitAll(task1,task2);
Console.WriteLine("main thread : continue my jobs...");


如果需要等待多个任务,任意1个完成就继续,只需将上述代码中的WaitAll改为WaitAny即可,参数一样。

 

TPL Part 1 Task 的使用

标签:

原文地址:http://blog.csdn.net/lan_liang/article/details/45112305

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!