使用任务代替ThreadPool和线程

  

GPS平台,网站建设,软件开发,系统运维,找森大网络科技!
http://cnsendnet.taobao.com
来自森大科技官方博客http://www.cnsendblog.com/index.php/?p=435

  

一:任务的优势

  

ThreadPool相比线程来说具备了很多优势,但是ThreadPool却又存在一些使用上的不方便,比如:

  

1: ThreadPool不支持线程的取消,完成,失败通知等交互性操作,

  

2: ThreadPool不支持线程执行的先后次序;

  

以往,如果开发者要实现上述功能,需要完成很多额外的工作,现在,FCL中提供了一个功能更强大的概念:Task.Task在线程池的基础上进行了优化,并提供了更多的API。在FCL4.0中,如果我们要编写多线程程序,任务显然已经优于传统的方式。

  

以下是一个简单的任务示例:

  
 <代码> staticvoid Main (string [] args)
  {
  任务t=新任务(()=比;
  {
  Console.WriteLine(“任务开始工作……”);//模拟工作过程
  thread . sleep (5000);
  });
  t.Start ();
  t.ContinueWith((任务)=比;
  {
  Console.WriteLine(“任务完成,完成时候的状态为:");
  控制台。WriteLine (“IsCanceled={0} \ tIsCompleted={1} \ tIsFaulted={2}”,任务。IsCanceled,任务。IsCompleted task.IsFaulted);
  });
  Console.ReadKey ();
  } 
  

二:任务的完成状态

  

任务任务有这样一些属性,让我们查询任务完成时的状态:

  

1: IsCanceled,因为被取消而完成;

  

2: IsCompleted,成功完成;

  

3: IsFaulted,因为发生异常而完成

  

需要注意的是,任务并没有提供回调事件来通知完成(像BackgroundWorker一样),它通过启用一个新任务的方式来完成类似的功能.ContinueWith方法可以在一个任务完成的时候发起一个新任务,这种方式天然就支持了任务的完成通知:我们可以在新任务中获取原任务的结果值。

  
 <代码>下面是一个稍微复杂一点的例子,同时支持完成通知,取消,获取任务返回值等功能: 
  
 <代码> staticvoid Main (string [] args)
  {
  时候触发的时候触发cts=new ();
  Taskt=新Task(()=比;添加(cts.Token) cts.Token);
  t.Start ();
  t.ContinueWith (TaskEnded);//等待按下任意一个键取消任务
  Console.ReadKey ();
  cts.Cancel ();
  Console.ReadKey ();
  }
  
  staticvoid TaskEnded (Task任务)
  {
  Console.WriteLine(“任务完成,完成时候的状态为:");
  控制台。WriteLine (“IsCanceled={0} \ tIsCompleted={1} \ tIsFaulted={2}”,任务。IsCanceled,任务。IsCompleted task.IsFaulted);
  控制台。WriteLine(“任务的返回值为:{0}”,task.Result);
  }
  
  staticint Add (CancellationToken ct)
  {
  Console.WriteLine(“任务开始……”);
  int结果=0;
  而(! ct.IsCancellationRequested)
  {
  结果+ +;
  thread . sleep (1000);
  }
  返回结果;
  } 
  

在任务开始后大概3秒钟的时候按下键盘,会得到如下的输出:

  

任务开始……
任务完成,完成时候的状态为:
IsCanceled=False IsCompleted=True IsFaulted=False
任务的返回值为:3
你也许会奇怪,我们的任务是通过取消的方式处理,为什么完成的状态IsCanceled那一栏还是假的。这是因为在工作任务中,我们对于IsCancellationRequested进行了业务逻辑上的处理,并没有通过ThrowIfCancellationRequested方法进行处理。如果采用后者的方式,如下:

  
 <代码> staticvoid Main (string [] args)
  {
  时候触发的时候触发cts=new ();
  Taskt=新Task(()=比;AddCancleByThrow (cts.Token) cts.Token);
  t.Start ();
  t.ContinueWith (TaskEndedByCatch);//等待按下任意一个键取消任务
  Console.ReadKey ();
  cts.Cancel ();
  Console.ReadKey ();
  }
  
  staticvoid TaskEndedByCatch (Task任务)
  {
  Console.WriteLine(“任务完成,完成时候的状态为:");
  控制台。WriteLine (“IsCanceled={0} \ tIsCompleted={1} \ tIsFaulted={2}”,任务。IsCanceled,任务。IsCompleted task.IsFaulted);
  试一试
  {
  控制台。WriteLine(“任务的返回值为:{0}”,task.Result);
  }
  抓住(AggregateException e)
  {
  e.Handle ((err)=比;犯错是OperationCanceledException);
  }
  }
  
  staticint AddCancleByThrow (CancellationToken ct)
  {
  Console.WriteLine(“任务开始……”);
  int结果=0;
  而(真)
  {
  ct.ThrowIfCancellationRequested ();
  结果+ +;
  thread . sleep (1000);
  }
  返回结果;
  }

使用任务代替ThreadPool和线程