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

1、Thread类可以创建和控制线程。Thread类的构造函数重载为接受ThreadStart和ParameterizedThreadStart委托类型参数。其中,ThreadStart委托要求函数为无参、返回值类型为void;ParameterizedThreadStart委托要求函数接受一个object类型参数,返回值类型同样为void。创建Thread类对象后,使用Start方法启动线程。

 1 using System;
 2 using System.Threading;
 3 
 4 class Program
 5 {
 6     static void Main(string[] args)
 7     {
 8         ThreadStart start = new ThreadStart(DoSomeThing);
 9         Thread thread = new Thread(start);
10         thread.Start();
11         Console.WriteLine("This is the main thread.");
12     }
13 
14     static void DoSomeThing()
15     {
16         Console.WriteLine("Running in a thread.");
17     }
18 }

运行结果:

不能保证输出结果的先后顺序,因为线程由操作系统调度。

2、可以使用函数名直接作为Thread类构造函数的参数。

 1 using System;
 2 using System.Threading;
 3 
 4 class Program
 5 {
 6     static void Main(string[] args)
 7     {
 8         Thread thread = new Thread(DoSomeThing);
 9         thread.Start();
10         Console.WriteLine("This is the main thread.");
11     }
12 
13     static void DoSomeThing()
14     {
15         Console.WriteLine("Running in a thread.");
16     }
17 }

 3、给线程传递数据可以采用两方式。一种方式是使用带ParameterizedThreadStart委托参数的Thread构造函数,另一种方式是创建一个自定义类,把线程的方法定义为实例方法。然后调用Thread类的Start方法,通过Start方法将参数传递给线程调用的函数。由于ParameterizedThreadStart委托要求的参数只能是object类型,所以在被线程调用的方法中对其进行类型转换。以下代码是第一种方式。

 1 using System;
 2 using System.Threading;
 3 
 4 class Person
 5 {
 6     public string Name;
 7     public int Age;
 8 
 9     public override string ToString()
10     {
11         return string.Format("The age of {0} is {1}", Name, Age);
12     }
13 }
14 
15 class Program
16 {
17     static void Main(string[] args)
18     {
19         Person person = new Person();
20         person.Name = "Tom";
21         person.Age = 20;
22         new Thread(DoSomeThing).Start(person);
23         Console.WriteLine("This is the main thread.");
24     }
25 
26     static void DoSomeThing(object obj)
27     {
28         Person person = (Person)obj;
29         Console.WriteLine("Running in a thread, the parameter is: {0}.", person);
30     }
31 }

运行结果:

4、以下代码是第二种方式。

 1 using System;
 2 using System.Threading;
 3 
 4 class Person
 5 {
 6     public string Name;
 7     public int Age;
 8 
 9     public Person(string name, int age)
10     {
11         this.Name = name;
12         this.Age = age;
13     }
14 
15     public void DoSomeThing()
16     {
17         Console.WriteLine("Running in a thread, the parameter is: {0}, and the id is: {1}.", this, Thread.CurrentThread.ManagedThreadId);
18     }
19 
20     public override string ToString()
21     {
22         return string.Format("The age of {0} is {1}", Name, Age);
23     }
24 }
25 
26 class Program
27 {
28     static void Main(string[] args)
29     {
30         Person person = new Person("Tom", 20);
31         new Thread(person.DoSomeThing).Start();
32         Console.WriteLine("This is the main thread, and the id is: {0}.", Thread.CurrentThread.ManagedThreadId);
33     }
34 }

运行结果:

5、与Lambda表达式可以与异步委托一起使用一样,Lambda表达式也可以在线程中使用。以下代码是无参数传递的例子。

 1 using System;
 2 using System.Threading;
 3 
 4 class Program
 5 {
 6     static void Main(string[] args)
 7     {
 8         new Thread(() => Console.WriteLine("Running in a thread, and the id is: {0}", Thread.CurrentThread.ManagedThreadId)).Start();
 9         Console.WriteLine("This is the main thread, and the id is: {0}.", Thread.CurrentThread.ManagedThreadId);
10     }
11 }

运行结果:略。

6、以下代码是有参数传递的例子。

 1 using System;
 2 using System.Threading;
 3 
 4 struct Point
 5 {
 6     public int X;
 7     public int Y;
 8 
 9     public override string ToString()
10     {
11         return string.Format("The point is X: {0}, Y: {1}", X, Y);
12     }
13 }
14 
15 class Program
16 {
17     static void Main(string[] args)
18     {
19         new Thread((obj) =>
20         {
21             Point point = (Point)obj;
22             Console.WriteLine("Running in a thread, the parameter is: {0}.", point);
23         }).Start(new Point() { X = 3, Y = 4 });
24         Console.WriteLine("This is the main thread.");
25     }
26 }

运行结果:

7、用Thread类创建线程时,可以设置IsBackground属性,以确定该线程是前台线程还是后台线程。该属性的默认值是false,即新创建的线程默认都是前台线程。

 1 using System;
 2 using System.Threading;
 3 
 4 class Program
 5 {
 6     static void Main(string[] args)
 7     {
 8         Console.WriteLine("The main thread is starting.");
 9         new Thread(() =>
10         {
11             Console.WriteLine("Thread: {0} started.", Thread.CurrentThread.Name);
12             Thread.Sleep(3000);
13             Console.WriteLine("Thread: {0} completed.", Thread.CurrentThread.Name);
14         }) { Name = "MyThread", IsBackground = false }.Start();
15         for (int i = 0; i < 11; i++)
16         {
17             Console.WriteLine("*");
18         }
19         Console.WriteLine("The main thread is ending now.");
20     }
21 }

运行结果:

从运行结果可以看到,尽管主线程已经结束,但是由于新建线程是前台线程,它仍会睡眠3秒钟,直到其结束后,整个程序才真正结束。

8、将代码中第14行的IsBackground设置为true以后,线程被设置为后台线程,当主线程结束后,整个程序随即结束。

运行结果:

从上面的结果中只能看到“Thread: MyThread started.”,而看不到上一例中的“Thread: MyThread completed.”。这种后台线程的例子如Word应用程序的拼写检查器,它会随着Word的关闭而关闭。

9、在Thread类中,可以设置Priority属性,以影响线程的基本优先级。Priority属性的类型是ThreadPriority枚举类型,该枚举类型包括有4个枚举值,它们分别是:Highest、AboveNormal、BelowNormal以及Lowest。

10、使用Thread类的Start方法可以创建线程,但是,在调用Start方法后,新创建的线程仍不是处于Running状态,而是处于Unstarted状态。只有操作系统的线程调度器选择了要运行的线程,线程才会改为Running状态。

11、ThreadPool类提供一个由操作系统维护的线程的容器。由于它是操作系统维护的,所以该类是一个表态类,不能也不必生成它的对象。

 1 using System;
 2 using System.Threading;
 3 
 4 class Program
 5 {
 6     static void Main(string[] args)
 7     {
 8         int workerThreads;
 9         int completionPortThreads;
10         ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
11         Console.WriteLine("Max worker threads: {0}, I/0 completion thread: {1}", workerThreads, completionPortThreads);
12     }
13 }

运行结果:

12、ThreadPool类的QueueUserWorkItem方法的参数是一个WaitCallback委托类型。WaitCallback委托类型与ParameterizedThreadStart委托类型一样,都要求函数接受一个object类型参数,返回值类型同样为void。

 1 using System;
 2 using System.Threading;
 3 
 4 class Program
 5 {
 6     static void Main(string[] args)
 7     {
 8         int workerThreads;
 9         int completionPortThreads;
10         ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
11         Console.WriteLine("Max worker threads: {0}, I/0 completion thread: {1}.", workerThreads, completionPortThreads);
12         for (int i = 0; i < 5; i++)
13         {
14             ThreadPool.QueueUserWorkItem(DoSomeThing);
15         }
16         Thread.Sleep(3000);
17     }
18 
19     static void DoSomeThing(object obj)
20     {
21         for (int i = 0; i < 3; i++)
22         {
23             Console.WriteLine("Loop {0}, running inside pooled thread {1}.", i, Thread.CurrentThread.ManagedThreadId);
24             Thread.Sleep(50);
25         }
26     }
27 }

运行结果:

posted @ 2016-05-31 19:22  如意猴™  阅读(290)  评论(0)    收藏  举报