在多線程這一系列文章中,我們將講述C#語言中多線程的相關知識,在多線程(基礎篇)中我們將學習以下知識點:
一、創建線程
在整個系列文章中,我們主要使用Visual Studio 2015作為線程編程的主要工具。在C#語言中創建、使用線程只需要按以下步驟編寫即可:
1、啟動Visual Studio 2016,新建一個控制台應用程序。
2、確保該控制台程序使用.NET Framework 4.6或以上版本。然而在該篇中的所有示例使用較低版本可以正常工作。
3、雙擊打開該控制台應用程序中的“Program.cs”文件,在其中編寫如下代碼:
1 using System;
2 using System.Threading;
3 using static System.Console;
4
5 namespace Recipe01
6 {
7 class Program
8 {
9 static void PrintNumbers()
10 {
11 WriteLine("Starting...");
12 for (int i = 1; i < 10; i++)
13 {
14 WriteLine(i);
15 }
16 }
17
18 static void Main(string[] args)
19 {
20 Thread t = new Thread(PrintNumbers);
21 t.Start();
22 PrintNumbers();
23 }
24 }
25 }
4、運行該控制台應用程序,運行效果(每次運行效果可能不同)如下圖所示:

在第2行代碼處,我們導入了System.Threading命名空間,該命名空間包含了我們編寫多線程程序所需要的所有類型。
在第3行代碼處,我們使用了C# 6.0的using static特性,使用了該特性之後,在代碼中允許我們在使用System.Console類型的靜態方法的時候不需要指定其類型名。
在第9~16行代碼處,我們定義了一個名為“PrintNumbers”的方法,該方法將在“Main”方法和線程中進行調用。
在第20行代碼處,我們創建了一個線程來運行“PrintNumbers”方法,當我們初始化一個線程時,一個“ThreadStart”或“ParameterizedThreadStart”委托的實例被傳遞給線程的構造方法。
在第21行代碼處,我們啟動線程。
在第22行代碼處,我們在“Main”方法中調用“PrintNumbers”方法。
二、中止線程
在這一節,我們將讓線程等待一些時間,在等待的這段時間內,該線程不會消耗操作系統的資源。編寫步驟如下:
1、使用Visual Studio 2015創建一個新的控制台應用程序。
2、雙擊打開“Program.cs”文件,編寫代碼如下所示:
1 using System;
2 using System.Threading;
3 using static System.Console;
4 using static System.Threading.Thread;
5
6 namespace Recipe02
7 {
8 class Program
9 {
10 static void PrintNumbers()
11 {
12 WriteLine("Starting...");
13
14 for(int i = 1; i < 10; i++)
15 {
16 WriteLine(i);
17 }
18 }
19
20 static void PrintNumbersWithDelay()
21 {
22 WriteLine("Starting...");
23
24 for(int i = 1; i < 10; i++)
25 {
26 Sleep(TimeSpan.FromSeconds(2));
27 WriteLine(i);
28 }
29 }
30
31 static void Main(string[] args)
32 {
33 Thread t = new Thread(PrintNumbersWithDelay);
34 t.Start();
35 PrintNumbers();
36 }
37 }
38 }
3、運行該控制台應用程序,運行效果(每次運行效果可能不同)如下圖所示:

在第20~29行代碼處,我們定義了一個新的方法“PrintNumbersWithDelay”,該方法將在我們新建的線程中運行。需要注意的是在第26行代碼處,我們使用了“Thread”類的靜態方法“Sleep”,該方法使得每次循環都會等待2秒鐘執行。
在第33行代碼處,我們創建一個新的線程來運行“PrintNumbersWithDelay”方法。
三、線程等待
在這一節中,我們將講述如何在一個線程執行完畢後,再執行剩余的代碼,要完成這個工作,我們不能使用Thread.Sleep方法,因為我們不知道另一個線程精確的執行時間。要使一個線程等待另一個線程執行完畢後再進行其他工作,只需要按下列步驟編寫代碼即可:
1、使用Visual Studio 2015創建一個新的控制台應用程序。
2、雙擊打開“Program.cs”文件,編寫如下代碼:
1 using System;
2 using System.Threading;
3 using static System.Console;
4 using static System.Threading.Thread;
5
6 namespace Recipe03
7 {
8 class Program
9 {
10 static void PrintNumbersWithDelay()
11 {
12 WriteLine("Starting...");
13
14 for(int i = 1; i < 10; i++)
15 {
16 Sleep(TimeSpan.FromSeconds(2));
17 WriteLine(i);
18 }
19 }
20
21 static void Main(string[] args)
22 {
23 WriteLine("Starting...");
24 Thread t = new Thread(PrintNumbersWithDelay);
25 t.Start();
26 t.Join();
27 WriteLine("Thread completed");
28 }
29 }
30 }
3、運行該控制台應用程序,運行效果如下圖所示:

在第26行代碼處,我們在“Main”方法中調用調用“t.Join”方法,該方法允許我們等待線程t執行完畢後,再執行“Main”方法中剩余的代碼。有了該技術,我們可以同步兩個線程的執行步驟。第一個線程等待第二個線程執行完畢後,再進行其他的工作,在第一個線程等待期間,第一個線程的狀態為“bolcked”狀態,和我們調用Thread.Sleep的狀態一樣。
四、終止線程
在這一節中,我們將講述如何終止另一個線程的執行。步驟如下:
1、使用Visual Studio 2015創建一個新的控制台應用程序。
2、雙擊打開“Program.cs”文件,編寫如下代碼:
1 using System;
2 using System.Threading;
3 using static System.Console;
4 using static System.Threading.Thread;
5
6 namespace Recipe04
7 {
8 class Program
9 {
10 static void PrintNumbers()
11 {
12 WriteLine("Starting...");
13
14 for (int i = 1; i < 10; i++)
15 {
16 WriteLine(i);
17 }
18 }
19
20 static void PrintNumbersWithDelay()
21 {
22 WriteLine("Starting...");
23 for (int i = 1; i < 10; i++)
24 {
25 Sleep(TimeSpan.FromSeconds(2));
26 WriteLine(i);
27 }
28 }
29
30 static void Main(string[] args)
31 {
32 WriteLine("Starting program...");
33 Thread t = new Thread(PrintNumbersWithDelay);
34 t.Start();
35 Thread.Sleep(TimeSpan.FromSeconds(6));
36 t.Abort();
37 WriteLine("A thread has been aborted");
38 t = new Thread(PrintNumbers);
39 t.Start();
40 PrintNumbers();
41 }
42 }
43 }
3、運行該控制台應用程序,運行效果(每次運行效果可能不同)如下圖所示:

在第36行代碼處,我們調用了“t.Abort”方法,該方法用於終止一個線程的執行。當Abort方法被調用時,會對目標線程注入“ThreadAbortException”異常,該異常將導致線程的終止,這是一種非常危險的操作,因為這個異常可能發生在任何時候,並有可能導致整個應用程序的銷毀。因此,不推薦使用Abort方法來終止一個線程的執行,我們可以向線程提供一個“CancellationToken”對象來取消一個線程的執行,這個技術我們將在後續講述。
未完待續!