阅读原文可以访问我的个人博客
什么是进程和线程?
在进行多线程学习之前,我们首先要搞懂线程和进程这两个概念。
- 进程: 当你浏览网页的时候可以边听着歌,同时你的QQ也打开了。此时,在你的Windows上运行的所有应用程序(QQ、QQ音乐、火狐浏览器)都可以被成为一个进程。
- 线程: 当你使用火狐浏览器阅读一个网页的时候,浏览器也同时可以在下载文件,此时浏览器为了让你在下载文件的同时可以你浏览网页,会开启两个线程来处理这种情况:一个线程用来浏览网页,另一个线程用来下载文件,这两个线程会各自做自己的事情互不干扰。
当系统创建一个进程的时候,会自动为进程创建一个线程,这个线程被成为应用进程的主线程。然后这个主线程会再创建更多的线程。
- 多线程原理: 对于所有要运行的线程,操作系统会轮流为每个线程分配一些CPU时间。它会采取循环的方式,为每个线程都分配时间片,从而营造出所有线程并行的"假象"。
创建线程
在开始线程编程之前先看几个线程相关的函数。
Thread thread = new Thread(ParameterizedThreadStart start);
为了开启一个新的线程,首先要初始化Thread类的新实例 thread, 参数start表示开始执行线程时要调用的方法委托。也就是说线程开始后会跳转到 start 函数内部运行。
thread.Start();
之后可以使用Thread类的方法Start()方法启动线程。
为了模拟使用浏览器阅读一个网页的时候,同时也可以下载文件。我们在程序中使用了两个线程:一个主线程和一个thread_donwnload线程,主线程会不断递增并打印阅读的进度,而thread_download线程会不断递增并打印下载的进度。程序具体程序如下 :
1 /*------------------------------------------------------- 2 written by helio, 2019 3 ThreadSample1 - 使用线程模拟边浏览网页边下载 4 --------------------------------------------------------- 5 using System; 6 using System.Threading; 7 8 namespace ConsoleApp1f 9 { 10 class Program 11 { 12 /// <summary> 13 /// 开启一个用来模拟下载的线程 14 /// </summary> 15 private static void Download() 16 { 17 Console.WriteLine("Download Start."); 18 for (int i = 0; i <= 100; i++) 19 Console.WriteLine("Downloading {0}%", i); 20 Console.WriteLine("Download finished!"); 21 } 22 23 /// <summary> 24 /// 主线程模拟阅读浏览器 25 /// </summary> 26 private static void Read() 27 { 28 Console.WriteLine("Read Start."); 29 for (int i = 0; i <= 100; i++) 30 Console.WriteLine("Reading {0}%", i); 31 Console.WriteLine("Reading finished!"); 32 } 33 34 static void Main(string[] args) 35 { 36 Thread thread_download = new Thread(Download); 37 thread_download.Start(); 38 39 Read(); 40 Console.ReadKey(); 41 } 42 } 43 }
程序运行结果可以观察到阅读进度和下载进度是在交替增加的,可以看出主线程和thread_download线程是在一种并行的状态,此时可以说我们成功的模拟了边浏览网页边下载。
其他线程相关函数
创建线程只是最基本的线程操作函数,如下表格列出了另外几个比较常用的线程操作函数。
名称 | 说明 |
Sleep方法 | 将当前线程挂起指定的时间 |
Join方法 | 将指定的线程合并到当前线程中,并阻止当前线程,直至指定的线程结束或者经过了指定时间。 |
Abort方法 | 在调用此方法的线程上引发 System.Threading.ThreadAbortException,以开始终止此线程的过程,调用此方法通常会终止线程。 |
现有三个要完成的任务Main、TaskOne、TaskTwo。要求如下:
- 第一个任务要和第二个任务同时执行.
- 第三个任务必须等到第二个任务开始后才能执行。
- 第二个任务必须等待第三个任务完成后才能继续其任务。
- 第三个任务需要执行到一半的时候终止。
为了实现上诉需求,我们首先要做的是在Main函数的主线程中开启一个线程用来执行TaskOne,之后在TaskOne线程中开启一个线程用来执行TaskTwo。
启动TaskTwo线程后,为了满足第三个条件,可以使用Join方法,使得TaskOne线程必须等待TakskTow线程执行完成轴才能继续执行;
为了使得TaskTwo执行到一半时终止,我们可以在TaskTwo所在的线程中使用Abort方法,强制终止线程。至此,上诉四个需求都可得到满足,具体实现见如下代码 :
1 /*------------------------------------------------------- 2 written by helio, 2019 3 ThreadSample2.cs - 完成三个任务 4 --------------------------------------------------------- 5 using System; 6 using System.Threading; 7 8 namespace ConsoleApp1 9 { 10 class Program 11 { 12 private static void TaskOne() 13 { 14 Console.WriteLine("Tack