《C#高级编程》读书笔记(十五):任务、线程和同步之二 任务

时间:2022-09-10 18:32:40

1,任务

    为了更好地控制并行动作,可以使用System.Threading.Tasks名称空间中的Task类。任务表示应完成的某个工作单元。这个工作单元可以在单独的线程中运行,也可以以同步方式启动一个任务,这需要等待主调线程。

    启动任务的几种方法:可以使用TaskFactory类或Task类的构造函数和Start()方法。

    第一种方式:实例化TaskFactory类,在其中把TaskMetho方法传递给StartNew方法,就会立即启动任务。

    第二种方式:使用Task类的静态熟悉Factory来访问TaskFactory,以及调用StartNew()方法。

    第三种方式:使用Task类的构造函数。实例化Task对象时,任务不会立即执行,调用Task类的Start()方法启动任务。

    第四种方式:调用Task类的Run方法,立即启动任务。

        private static void Main(string[] args)
        {
            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"));

            Console.ReadKey();
        }

        static object taskMethoLock = new object();

        static void TaskMethod(object title)
        {
            lock (taskMethoLock)
            {
                Console.WriteLine(title);
            }
        }

      执行结果:

using a task factory
factory via a task
using the Run method
using a task constructor and Start

    以上任务都是使用线程池中的线程,而且都是后台线程。

2,同步任务

    任务也可以同步运行,以相同的线程作为主调线程,也就是在前台线程中运行。

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

3,使用单独线程的任务

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

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

4,连续任务

    连续任务通过在任务上调用ContinueWith()方法来定义。也可以使用TaskFactory类来定义。

        private static void Main(string[] args)
        {
            Task t1 = new Task(DoOnFirst);
            Task t2 = t1.ContinueWith(DoOnSecond);
            t1.Start();
            Console.ReadKey();
        }

        static void DoOnFirst()
        {
            Console.WriteLine($"doing some task {Task.CurrentId}");
        }

        static void DoOnSecond(Task t)
        {
            Console.WriteLine($"task {t.Id} finished");
            Console.WriteLine($"this task id {Task.CurrentId}");
            Console.WriteLine("do the cleanup");
            Thread.Sleep(3000);
        }

 5,任务层次结构

     任务也可以构成一个层次结构。一个任务启动一个新任务时,就启动了一个父/子层次结构。创建子任务的代码与创建父任务的代码相同,唯一的区别是这个任务从另一个任务内部创建。

        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 {Task.CurrentId}");
            var child = new Task(ChildTask); child.Start();
            Thread.Sleep(1000);
            Console.WriteLine("parent started child");
        }

        static void ChildTask()
        {
            Console.WriteLine("child");
            Thread.Sleep(5000);
            Console.WriteLine("child finished");
        }