《C#高级编程》读书笔记(十五):任务、线程和同步之二 任务
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"); }