zoukankan      html  css  js  c++  java
  • 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

    执行结果:

  • 相关阅读:
    项目实践精解读后感(需求分析注意点)
    XP@Scrum
    项目实践精解读后感2(需求分析注意点)
    十一过后,反思。
    可以自动化功能测试了Selenium
    部分关键字段重复的记录(保留最后记录)
    算是代码优化吗?还可以继续优化吗?
    hql查询~
    通用权限管理设计 之 数据库结构设计(摘录)
    jQuery Liger~
  • 原文地址:https://www.cnblogs.com/hmliang/p/5398615.html
Copyright © 2011-2022 走看看