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

执行结果:

原文地址:https://www.cnblogs.com/hmliang/p/5398615.html