你的位置:首页 > ASP.net教程

[ASP.net教程]Task类(任务)


任务表示应完成的某个单元的工作。这个单元的工作可以在单独的线程中运行,也可以以同步方式启动一个任务,这需要等待主调用线程。使用任务不仅可以获得一个抽象层,还可以对底层线程进行很多控制。

1.启动任务

要启动任务,可以使用TaskFactory类或Task类的构造函数和Start()方法。Task类的构造函数在创建任务上提供的灵活性较大。

1).任务方法

  static object taskMethodLock = new object();  static void TaskMethod(object title)  {   lock (taskMethodLock)   {    Console.WriteLine(title);    Console.WriteLine("Task id: {0}, thread: {1}",     Task.CurrentId == null ? "no task" : Task.CurrentId.ToString(),     Thread.CurrentThread.ManagedThreadId);    Console.WriteLine("is pooled thread: {0}", Thread.CurrentThread.IsThreadPoolThread);    Console.WriteLine("is background thread: {0}", Thread.CurrentThread.IsBackground);    Console.WriteLine();   }  }

View Code

2).使用线程池的任务

  static void TasksUsingThreadPool()  {   var tf = new TaskFactory();   Task t1 = tf.StartNew(TaskMethod, "using a task factory");   Task t2 = Task.Factory.StartNew(TaskMethod, "factory via a task");   var t3 = new Task(TaskMethod, "using a task constructor and Start");   t3.Start();   Task t4 = Task.Run(() => TaskMethod("using the Run method"));  }

View Code

执行结果:

3).同步任务

任务也可以同步运行,已相同的线程作为主调用线程。

注:主线程是一个调用前台线程,没有任务ID,也不是线程池中的线程。

  private static void RunSynchronousTask()  {   TaskMethod("just the main thread");   var t1 = new Task(TaskMethod, "run sync");   t1.RunSynchronously();  }

View Code

执行结果:

4).使用单独线程的任务

如果任务的代码应该长时间运行,就应该使用TaskCreationOptions.LogRunning告诉任务调度器创建一个新线程,而不是使用线程池中的线程。

  private static void LongRunningTask()  {   var t1 = new Task(TaskMethod, "long running", TaskCreationOptions.LongRunning);   t1.Start();  }

View Code

执行结果:

2.Future——任务结果

任务结束时,它可以把一些有用的状态信息写到共享对象中。这个对象必须是线程安全的。另一个选项是使用返回某个结果的任务。这种任务也叫Future,因为它返回一个结果。

  static Tuple<int, int> TaskWithResult(object division)  {   Tuple<int, int> div = (Tuple<int, int>)division;   int result = div.Item1 / div.Item2;   int reminder = div.Item1 % div.Item2;   Console.WriteLine("task creates a result...");   return Tuple.Create<int, int>(result, reminder);  }

View Code
  static void ResultsFromTasks()  {   var t1 = new Task<Tuple<int, int>>(TaskWithResult, Tuple.Create<int, int>(8, 3));   t1.Start();   Console.WriteLine(t1.Result);   t1.Wait();   Console.WriteLine("result from task: {0} {1}", t1.Result.Item1, t1.Result.Item2);  }

View Code

执行结果:

3.连续任务

通过任务,可以指定在任务完成后,应开始运行另一个特定任务。

注:无论前一个任务是如何结束的,前面的连续任务总是在前一个任务结束时启动。使用TaskContinuationOptions枚举中的值,可以指定,连续任务只有在起始任务成功(或失败)结束时启动。一些可能的值是OnlyOnFaulted、NotOnFaulted、OnlyOnCanceled和OnlyOnRanToCompletion。

  static void DoOnFirst()  {   Console.WriteLine("doing some task {0}", Task.CurrentId);   Thread.Sleep(3000);  }  static void DoOnSecond(Task t)  {   Console.WriteLine("task {0} finished", t.Id);   Console.WriteLine("this task id {0}", Task.CurrentId);   Console.WriteLine("do some cleanup");   Thread.Sleep(3000);  }  static void DoOnError(Task t)  {   Console.WriteLine("task {0} had an error!", t.Id);   Console.WriteLine("my id {0}", Task.CurrentId);   Console.WriteLine("do some cleanup");  }

View Code
  static void ContinuationTask()  {   Task t1 = new Task(DoOnFirst);   Task t2 = t1.ContinueWith(DoOnSecond);   Task t3 = t1.ContinueWith(DoOnSecond);   Task t4 = t2.ContinueWith(DoOnSecond);   Task t5 = t1.ContinueWith(DoOnError, TaskContinuationOptions.OnlyOnFaulted);   t1.Start();   Thread.Sleep(5000);  }

View Code

执行结果:

4.任务层次结构

利用任务连续性,可以在一个任务结束后启动另一个任务。任务也可以构成一个层次结构。一个任务启动一个新任务时,就启动了一个父/子层次结构。

如果父任务在子任务之前结束,父任务的状态就显示为:WaitingForChildrenToComplete。所有的子任务也结束时,父任务的状态就变成RanToCompletion。

static void ParentAndChild()  {   var parent = new Task(ParentTask);   parent.Start();   Thread.Sleep(2000);   Console.WriteLine(parent.Status);   Thread.Sleep(4000);   Console.WriteLine(parent.Status);  }  static void ParentTask()  {   Console.WriteLine("task id {0}", Task.CurrentId);   var child = new Task(ChildTask); // , TaskCreationOptions.DetachedFromParent);   child.Start();   Thread.Sleep(1000);   Console.WriteLine("parent started child");   // Thread.Sleep(3000);  }  static void ChildTask()  {   // Console.WriteLine("task id {0}, parent: {1}", Task.Current.Id, Task.Current.Parent.Id);   Console.WriteLine("child");   Thread.Sleep(5000);   Console.WriteLine("child finished");  }

View Code

执行结果: