.NET4.0多线程编程---Tasks

写在前面的话

  不得不说4.0里面新增的task实在是让人耳目一新,曾经在thread里面查找当线程abort等等操作的时候有没有相应的事件,就像gridview在分页、绑定的时候会产生事件一样,但是在thread里面是没有找到。然而task里面这些都实现了,虽然不是以事件的方式实现,但是它真的实现了。很让人兴奋。

一、概述 

  在上一篇文章.NET4.0多线程编程---Cooperative Cancellation提到线程池没有提供任何内在的方法告诉我们操作什么时候完成,在线程完成了以后,我们也没有任何方法可以获取一个返回值。

  为了弥补上述不足,微软在.NET4.0里面提出了任务的概念(Task),下面的两种方式产生的结果是一样的

 
  
ThreadPool.QueueUserWorkItem(Sum, 5 ); // 使用线程池
new Task(Sum, 5 ).Start();//使用Task

 

  上面线程池是由cpu自己操作的,而task需要程序手动去Start。

 

  对于task,在使用其构造函数的时候可以传递Action(向上面只传递没有参数的函数),也可以传递Action<object>(有参数的函数),还可以传递CancelationToken(用于接收取消的命令,这样描述感觉才对,token啊)

二、等待一个Task完成,并且获取其执行结果

  要想获取执行结果,我们必须构造一个Task<TResult>对象,TResult必须要和即将要和绑定的方法的返回值相匹配。等待调用其Wait方法。写了一个小例子。

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
namespace Alex.Net4MultiThread.MyTask
{
internal class OwnTask
{

public static void Main()
{
Task
< int > t = new Task < int > (n => Sum(( int )n), 10 );

t.Start();
t.Wait();//等待
Console.WriteLine(t.Result);
// 900
}
private static int Sum( int n)
{
int sum = 0 ;
for (; n < 100 ; n ++ )
{
Thread.Sleep(
10 );
sum
+= 10 ;
}
return sum;
}
}

}

 

 

  在上面代码中如果在调用Wait时,task已经开始执行,那么程序会阻止当前线程一直等待到task完成为止(犹如thread所示)。而如果在调用wait时,task还没有开始执行,那么当前线程是不会阻止的。

  当在一个任务中产生异常,任务会正常返回,但是当调用Wait或者Result的时候系统会抛出System.AggregateException异常。

三、取消一个Task

  可是使用CancellationTokenSource来取消一个task,如果考虑到又可能要取消一个task,那么对应的方法应该接受一个CancellationToken参数(用于通知被取消)。上代码。

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
namespace Alex.Net4MultiThread.MyTask
{
internal class OwnTask
{

public static void Main()
{
CancellationTokenSource cts
= new CancellationTokenSource();
Task
< int > t = new Task < int > (() => Sum(cts.Token, 10 ), cts.Token);

t.Start();
cts.Cancel();
// 取消
try
{
// 在调用Wait或者Result时会返回目标操作中的异常
Console.WriteLine(t.Result); // 900
}
catch (AggregateException ex)
{
ex.Handle(e
=> e is OperationCanceledException);
Console.WriteLine(
" Sum was canceled " );
}
}
private static int Sum(CancellationToken ct, int n)
{
int sum = 0 ;
for (; n < 100 ; n ++ )
{
ct.ThrowIfCancellationRequested();
// 如果被通知取消,则会抛出异常
sum += 10 ;
}
return sum;
}
}
}

  上面的操作真的是很让人激动的,比起Thread.Abort实在是太好了。对于取消。如果在取消时Task还没有Start,那么task将不会执行。

四、当其他任务完成的时候,自动开始一个新的任务

  在前面的例子中,我们wait一个task或者要获取一个task的Result,等待其实是很花费系统资源的,在Task编程模式下,大多时候我们都无需等待,只需注册一个新的task,该task在当前task完成时执行,此时我们可以对Result进行操作。

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
namespace Alex.Net4MultiThread.MyTask
{
internal class OwnTask
{

public static void Main()
{
Task
< int > t = new Task < int > (n => Sum(( int )n), 10 );

t.Start();
//
Task cwt = t.ContinueWith(task => Console.WriteLine( " The sum is : "
            + task.Result)); // 900
Console.Read();
}
private static int Sum( int n)
{
int sum = 0 ;
for (; n < 100 ; n ++ )
{
sum
+= 10 ;
}
return sum;
}
}
}

 

  上面代码中新的任务(注册)是通过ContinueWith来完成的,该函数也返回一个task,但是一般情况下直接忽略其返回值,而应该将注意力集中在其逻辑,“注册什么,注册的task做什么,应该在什么时候让其执行。。。”,比如在上例中,注册的task在主task结束时打印出主task的执行结果。

 

  其实上面的代码是在主task完成之后执行某注册的task,其实ContinueWith函数还接受一个TaskContinuationOptions枚举参数。有8-9个值吧,我主要演示3个,具体功能如其名所示。

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
t.ContinueWith(task => Console.WriteLine( " The sum is : " + task.Result),
TaskContinuationOptions.OnlyOnRanToCompletion);
// 主task成功时执行当前产生的task
t.ContinueWith(task => Console.WriteLine( " The sum is : " + task.Result),
TaskContinuationOptions.OnlyOnFaulted);
// 主task失败执行当前产生的task
t.ContinueWith(task => Console.WriteLine( " The sum is : " + task.Result),
TaskContinuationOptions.OnlyOnCanceled);
// 主task取消执行当前产生的task

 

还有一些内容包含子task,task factories等等。明天吧,累了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值