线程、任务和同步学习笔记(三)

1、要使用Task类,必须要引用System.Threading.Tasks命名空间。

 1 using System;
 2 using System.Threading;
 3 using System.Threading.Tasks;
 4 
 5 class Program
 6 {
 7     static void Main(string[] args)
 8     {
 9         // Using task factory
10         TaskFactory factory = new TaskFactory();
11         Task task1 = factory.StartNew(TaskMethod);
12 
13         Thread.Sleep(10);
14     }
15 
16     static void TaskMethod()
17     {
18         Console.WriteLine("Running in a task.");
19         Console.WriteLine("Task id: {0}.", Task.CurrentId);
20     }
21 }

运行结果:

若没有第11行代码,则一定不会输出结果。但如果Sleep方法的参数很小(如设置为1),则出现上图中所示结果的概率也会很小。

2、创建任务的方式有3种,分别是使用TaskFactory对象的StartNew方法、Task类的静态Factory属性的StartNew方法以及Task类的构造函数。

 1 using System;
 2 using System.Threading;
 3 using System.Threading.Tasks;
 4 
 5 class Program
 6 {
 7     static void Main(string[] args)
 8     {
 9         // Using task factory
10         TaskFactory factory = new TaskFactory();
11         Task task1 = factory.StartNew(TaskMethod);
12 
13         // Using the task factory via a task
14         Task task2 = Task.Factory.StartNew(TaskMethod);
15 
16         // Using Task constructor
17         Task task3 = new Task(TaskMethod);
18         task3.Start();
19 
20         Thread.Sleep(10);
21     }
22 
23     static void TaskMethod()
24     {
25         Console.WriteLine("Running in a task.");
26         Console.WriteLine("Task id: {0}.", Task.CurrentId);
27     }
28 }

运行结果:

3、以上3种方式都可以传递TaskCreationOptions枚举中的值。

 1 using System;
 2 using System.Threading;
 3 using System.Threading.Tasks;
 4 
 5 class Program
 6 {
 7     static void Main(string[] args)
 8     {
 9         // Using task factory
10         TaskFactory factory = new TaskFactory();
11         Task task1 = factory.StartNew(TaskMethod);
12 
13         // Using the task factory via a task
14         Task task2 = Task.Factory.StartNew(TaskMethod);
15 
16         // Using Task constructor
17         Task task3 = new Task(TaskMethod);
18         task3.Start();
19 
20         Task task4 = new Task(TaskMethod, TaskCreationOptions.PreferFairness);
21         task4.Start();
22         Thread.Sleep(10);
23     }
24 
25     static void TaskMethod()
26     {
27         Console.WriteLine("Running in a task.");
28         Console.WriteLine("Task id: {0}.", Task.CurrentId);
29     }
30 }

运行结果:

4、相较于线程,任务具有连续性,可以指定在任务完成后,应开始执行的另一个特定任务。例如,一个使用前一个任务的结果的新任务,即如果前一个任务失败了,这个任务就应执行一些清理工作。使用Task类对象的ContinueWith方法可以实现连续任务的连接。

 1 using System;
 2 using System.Threading;
 3 using System.Threading.Tasks;
 4 
 5 class Program
 6 {
 7     static void Main(string[] args)
 8     {
 9         Task task1 = new Task(DoOnFirst);
10         task1.Start();
11         Task task2 = task1.ContinueWith(DoOnSecond);
12         Task task3 = task1.ContinueWith(DoOnSecond);
13         Task task4 = task3.ContinueWith(DoOnSecond);
14         Thread.Sleep(1000);
15     }
16 
17     static void DoOnFirst()
18     {
19         Console.WriteLine("Do some task, the task id: {0}.", Task.CurrentId);
20         Thread.Sleep(100);
21     }
22 
23     static void DoOnSecond(Task task)
24     {
25         Console.WriteLine("Task {0} finished.", task.Id);
26         Console.WriteLine("This task id: {0}.", Task.CurrentId);
27         Console.WriteLine("Do some cleanup...");
28         Thread.Sleep(100);
29     }
30 }

运行结果:

从上图运行结果分析,ContinueWith方法会将其参数所指定的内容创建为新的任务并运行。然而,执行的次序并不能确定。

5、利用任务的连续性,可以在一个任务结束后启动另一个任务,从而构成一个层次结构(或者称其为父子结构)。

 1 using System;
 2 using System.Threading;
 3 using System.Threading.Tasks;
 4 
 5 class Program
 6 {
 7     static void Main(string[] args)
 8     {
 9         Task parent = new Task(ParentTask);
10         parent.Start();
11         Thread.Sleep(2000);
12         Console.WriteLine("Status: " + parent.Status);
13         Thread.Sleep(4000);
14         Console.WriteLine("Status: " + parent.Status);
15     }
16 
17     static void ParentTask()
18     {
19         Console.WriteLine("Task id {0}.", Task.CurrentId);
20         Task child = new Task(ChildTask);
21         child.Start();
22         Thread.Sleep(1000);
23         Console.WriteLine("Parent finished, and start child.");
24     }
25 
26     static void ChildTask()
27     {
28         Console.WriteLine("Child started.");
29         Thread.Sleep(5000);
30         Console.WriteLine("Child finished.");
31     }
32 }

运行结果:

6、由上述第4条可知,任务是可以有结果的。任务结束时,可以将某些有用的信息写到线程安全的共享对象中。或者使用Task类的泛型版本,定义返回某个结果的任务的返回类型。然而,在C# 5以后,Task类对象的Result属性已经不存在了,即《C# 高级编程(中文第七版)》中如下的例子不能正常编译。

 1 using System;
 2 using System.Threading;
 3 using System.Threading.Tasks;
 4 
 5 class Program
 6 {
 7     static void Main(string[] args)
 8     {
 9         Task task = new Task<Tuple<int, int>>(TaskWithResult, Tuple.Create<int, int>(8, 3));
10         task.Start();
11         Console.WriteLine(task.Result);
12     }
13 
14     static Tuple<int, int> TaskWithResult(object obj)
15     {
16         Tuple<int, int> tuple = (Tuple<int, int>)obj;
17         int division = tuple.Item1 / tuple.Item2;
18         int reminder = tuple.Item1 % tuple.Item2;
19         return Tuple.Create<int, int>(division, reminder);
20     }
21 }

编译结果:

不知微软取消该属性的原因为何?且在新版本中该功能如何实现?有待于进一步学习研究。

posted @ 2016-05-31 21:41  如意猴™  阅读(274)  评论(0编辑  收藏  举报