第13章C#高級特性_第1頁
第13章C#高級特性_第2頁
第13章C#高級特性_第3頁
第13章C#高級特性_第4頁
第13章C#高級特性_第5頁
已閱讀5頁,還剩73頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、第第13章章C#高級特性高級特性13.1 泛泛 型型13.2 反反 射射13.3 多線程程序設計多線程程序設計 13.1 泛泛 型型13.1.1 什么是泛型什么是泛型所謂泛型,是指通過參數化類型來實現在同一份代碼所謂泛型,是指通過參數化類型來實現在同一份代碼上操作多種數據類型,泛型編程是一種編程范式,它利用上操作多種數據類型,泛型編程是一種編程范式,它利用“參數化類型參數化類型”將類型抽象化,從而實現更為靈活的復用。將類型抽象化,從而實現更為靈活的復用。泛型類型和普通類型的區別在于泛型類型與一組類型參數泛型類型和普通類型的區別在于泛型類型與一組類型參數或類型變量關聯。或類型變量關聯。C#泛型能

2、力是由泛型能力是由CLR在運行時支持,區別于在運行時支持,區別于C+的編的編譯時模板機制和譯時模板機制和Java的編譯時的的編譯時的“搽拭法搽拭法”。這使得泛型。這使得泛型能力可以在各個支持能力可以在各個支持CLR的語言之間進行無縫的互操作。的語言之間進行無縫的互操作。數據的抽象:數據的抽象:int MAX(int a,int b) return ab?a:b; double MAX1(double a,double b) return ab?a:b; int MAX(int a,int b) return ab?a:b; double MAX(double a,double b) retur

3、n ab?a:b; 重載重載數據類型的抽象:數據類型的抽象: T MAX(T a,T b) return ab?a:b; 泛型泛型13.1.2 泛型的聲明和使用泛型的聲明和使用通常先聲明泛型,然后通過類型實例化來使用泛型。通常先聲明泛型,然后通過類型實例化來使用泛型。定義泛型的語法格式如下:定義泛型的語法格式如下:訪問修飾符訪問修飾符返回類型返回類型 泛型名稱泛型名稱其中,其中,“泛型名稱泛型名稱”要符合標識符的定義。尖括號要符合標識符的定義。尖括號表示類型參數列表,可以包含一個或多個類型參數,如表示類型參數列表,可以包含一個或多個類型參數,如。C#中常用的泛型有泛型類和泛型方法,例如:中常用

4、的泛型有泛型類和泛型方法,例如:class Stack/聲明泛型類聲明泛型類 T dataMaxSize;int top;void swap(ref T a,ref T b)/定義泛型方法定義泛型方法 T tmp = a;a = b;b = tmp;【例【例13.0】 分析以下程序執行結果。分析以下程序執行結果。 public class abc public A a; public B b; public void show() MessageBox.Show(a.ToString() + ,+b.ToString(); private void button2_Click(object s

5、ender, EventArgs e) abc a = new abc(); a.a = 2; a.b = 3.8; a.show(); 【例【例13.1】 分析以下程序的執行結果。分析以下程序的執行結果。using System;namespace Proj13_1class Stack/聲明棧泛型類聲明棧泛型類int maxsize;/棧中元素最多個數棧中元素最多個數T data;/存放棧中存放棧中T類型的元素類型的元素int top;/棧頂指針棧頂指針public Stack()/構造函數構造函數maxsize = 10;data = new Tmaxsize;top = -1;publ

6、ic Stack(int n)/重載構造函數重載構造函數maxsize = n;data = new Tmaxsize;top = -1;public bool StackEmpty()/判斷棧空方法判斷棧空方法 return top = -1; public bool Push(T e)/元素元素e進棧方法進棧方法 if (top = maxsize - 1)/棧滿返回棧滿返回false return false; top+; datatop = e; return true; public bool Pop(ref T e) /元素出棧方法元素出棧方法 if (top = -1)/棧空返回

7、棧空返回false return false; e = datatop; top-; return true; class Program static void Main(string args) int e = 0; Stack s = new Stack();/定義整數棧定義整數棧 s.Push(1);/進棧進棧3個整數個整數 s.Push(3); s.Push(2); Console.Write(整數棧出棧次序:整數棧出棧次序:); while (!s.StackEmpty()/棧不空時出棧元素棧不空時出棧元素 s.Pop(ref e); Console.Write(0 , e); C

8、onsole.WriteLine(); string e1 = ;Stack s1 = new Stack(); /定義字符串棧定義字符串棧s1.Push(Mary);/進棧進棧3個字符串個字符串s1.Push(John);s1.Push(Simth);Console.Write(字符串棧出棧次序:字符串棧出棧次序:);while (!s1.StackEmpty()/棧不空時出棧元素棧不空時出棧元素 s1.Pop(ref e1); Console.Write(0 , e1);Console.WriteLine(); 本程序先聲明了一個泛型棧本程序先聲明了一個泛型棧Stack,然后實例化為,然后

9、實例化為整數棧整數棧s和字符串棧和字符串棧s1,各自進棧,各自進棧3個元素后并出棧,程序個元素后并出棧,程序執行結果如圖執行結果如圖13.1所示。所示。13.2 反反 射射13.2.1 反射概述反射概述反射是一種機制,通過這種機制可以知道一個未知類反射是一種機制,通過這種機制可以知道一個未知類型的類型信息。型的類型信息。例如有一個對象,它不是我們定義的,既可能是通過例如有一個對象,它不是我們定義的,既可能是通過網絡捕捉到的,也可能是使用泛型定義的,但我們想知道網絡捕捉到的,也可能是使用泛型定義的,但我們想知道這個對象的類型信息,想知道這個對象有哪些方法或者屬這個對象的類型信息,想知道這個對象有

10、哪些方法或者屬性什么的,甚至想進一步調用這個對象的方法。關鍵是現性什么的,甚至想進一步調用這個對象的方法。關鍵是現在只知道它是一個對象,不知道它的類型,自然不會知道在只知道它是一個對象,不知道它的類型,自然不會知道它有哪些方法等信息,這時該怎么辦呢?它有哪些方法等信息,這時該怎么辦呢?反射機制就是解決這么一個問題的,通過反射機制就反射機制就是解決這么一個問題的,通過反射機制就可以知道未知類型對象的類型信息。可以知道未知類型對象的類型信息。反射提供了封裝程序集、模塊和類型的對象(反射提供了封裝程序集、模塊和類型的對象(Type類類型),可以使用反射動態創建類型的實例,將類型綁定到型),可以使用反

11、射動態創建類型的實例,將類型綁定到現有對象,或從現有對象獲取類型并調用其方法或訪問其現有對象,或從現有對象獲取類型并調用其方法或訪問其字段和屬性。如果代碼中使用了屬性,可以利用反射對它字段和屬性。如果代碼中使用了屬性,可以利用反射對它們進行訪問。們進行訪問。歸納起來,反射在下列情況下很有用:歸納起來,反射在下列情況下很有用:l 需要訪問程序元數據的屬性。需要訪問程序元數據的屬性。l 檢查和實例化程序集中的類型。檢查和實例化程序集中的類型。l 在運行時構建新類型。在運行時構建新類型。l 執行后期綁定,訪問在運行時創建的類型的方法。執行后期綁定,訪問在運行時創建的類型的方法。13.2.2 反射中常

12、用的類反射中常用的類1. Type類類System.Reflection是反射的命名空間,而是反射的命名空間,而Type類為類為System.Reflection功能的根,也是訪問元數據的主要方式。功能的根,也是訪問元數據的主要方式。Type類表示類型聲明,包括類類型、接口類型、數組類表示類型聲明,包括類類型、接口類型、數組類型、值類型、枚舉類型、類型參數、泛型類型定義,以類型、值類型、枚舉類型、類型參數、泛型類型定義,以及開放或封閉構造的泛型類型。及開放或封閉構造的泛型類型。公共屬性公共屬性說明說明IsAbstract獲取一個值,通過該值指示獲取一個值,通過該值指示Type是否為抽象的并且必

13、須被重是否為抽象的并且必須被重寫寫IsArray獲取一個值,通過該值指示獲取一個值,通過該值指示Type是否為數組是否為數組IsByRef獲取一個值,通過該值指示獲取一個值,通過該值指示Type是否由引用傳遞是否由引用傳遞IsClass獲取一個值,通過該值指示獲取一個值,通過該值指示Type是否是一個類,即不是值類是否是一個類,即不是值類型或接口型或接口IsInterface獲取一個值,通過該值指示獲取一個值,通過該值指示Type是否為接口,即不是類或值是否為接口,即不是類或值類型類型IsSubclassOf確定當前確定當前Type表示的類是否是從指定的表示的類是否是從指定的Type表示的類派

14、生的表示的類派生的MakeArrayType返回一個表示當前類型的一維數組(下限為零)的返回一個表示當前類型的一維數組(下限為零)的Type對象對象Module獲取在其中定義當前獲取在其中定義當前Type的模塊的模塊Name獲取當前成員的名稱獲取當前成員的名稱Namespace獲取獲取Type的命名空間的命名空間ReflectedType獲取用于獲取該成員的類對象獲取用于獲取該成員的類對象Type類的屬性類的屬性方法方法說明說明GetElementType當在派生類中重寫時,返回當前數組、指針或引用類型包含的當在派生類中重寫時,返回當前數組、指針或引用類型包含的或引用的對象的或引用的對象的Ty

15、peGetEvent獲取由當前獲取由當前Type聲明或繼承的特定事件聲明或繼承的特定事件GetEvents獲取由當前獲取由當前Type聲明或繼承的事件聲明或繼承的事件GetField獲取當前獲取當前Type的特定字段的特定字段GetFields獲取當前獲取當前Type的字段的字段GetInterface獲取由當前獲取由當前Type實現或繼承的特定接口實現或繼承的特定接口GetInterfaces當在派生類中重寫時,獲取由當前當在派生類中重寫時,獲取由當前Type實現或繼承的所有接口實現或繼承的所有接口GetMember獲取當前獲取當前Type的指定成員的指定成員GetMembers獲取當前獲取

16、當前Type的成員(包括屬性、方法、字段、事件等)的成員(包括屬性、方法、字段、事件等)GetMethod獲取當前獲取當前Type的特定方法的特定方法GetMethods獲取當前獲取當前Type的方法的方法GetProperties獲取當前獲取當前Type的屬性的屬性GetProperty獲取當前獲取當前Type的特定屬性的特定屬性InvokeMember使用指定的綁定約束并匹配指定的參數列表,調用指定成員使用指定的綁定約束并匹配指定的參數列表,調用指定成員Type類的方法類的方法歸納起來,得到一個歸納起來,得到一個Type實例的三種方法如下:實例的三種方法如下:(1)使用)使用System.

17、Object.GetType(),例如:,例如:Person pe=new Person();/定義定義pe為為person類的一個對象類的一個對象Type t=pe.GetType();這樣這樣t為為pe的的Type對象。對象。(2)使用)使用System.Type.GetType()靜態方法,參數為靜態方法,參數為類型的完全限定名。例如:類型的完全限定名。例如:Type t=Type.GetType(MyNs.Person);其中,其中,MyNs.Person為為MyNs命名空間中的命名空間中的Person類,類,這樣這樣t為該類的為該類的Type對象。對象。(3)使用)使用typeof運

18、算符,例如:運算符,例如:Type t=typeof(Person);其中其中Person為一個類,這樣為一個類,這樣t為該類的為該類的Type對象。對象。2. System.Reflection反射命名空間反射命名空間System.Reflection反射命名空間包含提供加載類型、反射命名空間包含提供加載類型、方法和字段的有組織的視圖的類和接口,具有動態創建方法和字段的有組織的視圖的類和接口,具有動態創建和調用類型的功能。其中主要的類及其功能如下:和調用類型的功能。其中主要的類及其功能如下:l Assembly類類:通過它可以加載、了解和操作一個程:通過它可以加載、了解和操作一個程序集。序集

19、。l AssemblyName類類:通過它可以找到大量隱藏在程:通過它可以找到大量隱藏在程序集的身份中的信息,如版本信息、區域信息等。序集的身份中的信息,如版本信息、區域信息等。l ConstructorInfo類類:用于發現構造函數及調用構造:用于發現構造函數及調用構造函數。通過對函數。通過對ConstructorInfo調用調用Invoke來創建對來創建對象,其中象,其中ConstructorInfo是由是由Type對象的對象的GetConstructors或或GetConstructor方法返回的。方法返回的。l EventInfo類類:通過它可以找到事件的信息。:通過它可以找到事件的信

20、息。l FieldInfo類類:通過它可以找到字段的信息。:通過它可以找到字段的信息。l MethodInfo類類:通過它可以找到方法的信息。:通過它可以找到方法的信息。l ParameterInfo類類:通過它可以找到參數的信息。:通過它可以找到參數的信息。l PropertyInfo類類:通過它可以找到屬性的信息。:通過它可以找到屬性的信息。l MemberInfo類類:它是一個抽象基類,為:它是一個抽象基類,為EventInfo、FieldInfo、MethodInfo、PropertyInfo等類型定義了等類型定義了公共的行為。公共的行為。l Module類類:用來訪問帶有多文件程序集

21、的給定模塊。:用來訪問帶有多文件程序集的給定模塊。l DefaultMemberAttribute類類:定義某類型的成員,該:定義某類型的成員,該成員是成員是InvokeMember使用的默認成員。使用的默認成員。 公共屬性公共屬性說明說明EntryPoint獲取此程序集的入口點獲取此程序集的入口點FullName獲取程序集的顯示名稱獲取程序集的顯示名稱Location獲取包含清單的已加載文件的路徑或位置獲取包含清單的已加載文件的路徑或位置ManifestModule獲取包含當前程序集清單的模塊獲取包含當前程序集清單的模塊其中重要的其中重要的Assembly類,它的常用屬性和常用方法類,它的常

22、用屬性和常用方法如下。如下。Assembly類的常用屬性類的常用屬性 方法方法說明說明GetFiles獲取程序集清單文件表中的文件獲取程序集清單文件表中的文件GetModule獲取此程序集中的指定模塊獲取此程序集中的指定模塊GetModules獲取作為此程序集的一部分的所有模塊獲取作為此程序集的一部分的所有模塊GetType獲取表示指定類型的獲取表示指定類型的Type對象對象GetTypes獲取此程序集中定義的類型獲取此程序集中定義的類型LoadFile加載程序集文件的內容加載程序集文件的內容LoadFrom在已知程序集的文件名或路徑等信息時加載程序集在已知程序集的文件名或路徑等信息時加載程序

23、集LoadModule加載此程序集的內部模塊加載此程序集的內部模塊Assembly類的常用方法類的常用方法 13.2.3 反射的應用示例反射的應用示例1. 通過反射查看類型的成員信息通過反射查看類型的成員信息查看類型信息的過程如下:查看類型信息的過程如下:(1)獲取指定類型的一個)獲取指定類型的一個Type對象或對象或Type對象數組。對象數組。(2)通過)通過Type類的許多方法來發現與該類型的成員有類的許多方法來發現與該類型的成員有關的信息。關的信息。【例【例13.2】 編寫一個程序,通過反射輸出編寫一個程序,通過反射輸出System.Object類的方法、字段和構造函數的信息。類的方法、

24、字段和構造函數的信息。解解:先通過:先通過Type的的GetTypes()方法獲取方法獲取System.Object類類的的Type對象對象t,然后用,然后用Type類的類的GetMethods()、GetFields()、GetConstructors()分別獲取分別獲取t對象的方法、字段和構造函數信對象的方法、字段和構造函數信息并輸出。程序如下:息并輸出。程序如下:using System;using System.Reflection;namespace Proj8_2class Programstatic void Main(string args) string classname

25、= System.Object;Console.WriteLine(0類類,classname);Type t = Type.GetType(classname);MethodInfo m = t.GetMethods();Console.WriteLine( 0的方法個數的方法個數:1, t.FullName, m.Length);foreach(MethodInfo item in m) Console.WriteLine(t0 ,item.Name); FieldInfo f = t.GetFields(); Console.WriteLine( 0的字段個數的字段個數:1, t.Ful

26、lName, f.Length); foreach (FieldInfo item in f) Console.WriteLine(t0 , item.Name); ConstructorInfo c = t.GetConstructors();Console.WriteLine( 0的構造函數個數的構造函數個數:1, t.FullName, c.Length);foreach (ConstructorInfo item in c)Console.WriteLine(t0 , item.Name); 程序執行結果程序執行結果2. 通過反射調用未知類的某方法通過反射調用未知類的某方法調用未知類的

27、某方法的過程如下:調用未知類的某方法的過程如下:(1)假設一個未知類)假設一個未知類c屬于某個屬于某個DLL文件文件xyz.dll,采,采用用Assembly.LoadFrom(xyz.dll)加載該程序集。加載該程序集。(2)調用)調用assembly.GetTypes()方法得到一個方法得到一個Type對對象數組象數組t。(3)通過)通過Type.GetConstructor()方法得到某個對象方法得到某個對象的構造函數。的構造函數。(4)通過)通過ConstructorInfo.Invoke()方法調用構造函方法調用構造函數創建未知類的對象數創建未知類的對象s。(5)通過對象)通過對象s

28、調用某方法。調用某方法。【例【例13.3】 有一個項目有一個項目Proj8_3,通過添加代碼文件模,通過添加代碼文件模板向其中添加一個板向其中添加一個Sport.cs文件,該文件的內容如下:文件,該文件的內容如下:using System;public abstract class Sport/體育運動類體育運動類protected string name; /項目名項目名public abstract string GetDuration();/獲取比賽時間獲取比賽時間public abstract string GetName();/獲取項目名獲取項目名在命令行方式下使用以下命令生成在命令

29、行方式下使用以下命令生成Sport.dll文件:文件:csc/target:library Sport.cs命令行編譯命令命令行編譯命令 采用命令行方式對采用命令行方式對C#文件進行編譯的程序是文件進行編譯的程序是csc.exe,它通常位于系統目,它通常位于系統目錄下的錄下的Microsoft.NETFramework文件夾中,根據每臺計算機上的文件夾中,根據每臺計算機上的確 切 配 置 , 此 位 置 可 能 有 所 不 同 。 一 般 情 況 下 其 位 置 是確 切 配 置 , 此 位 置 可 能 有 所 不 同 。 一 般 情 況 下 其 位 置 是C:WindowsMicrosoft

30、.NETFrameworkv2.0.50727文件夾中。文件夾中。 為了進行命令行編譯,在為了進行命令行編譯,在Windows下運行下運行cmd命令,進入存放項目的文命令,進入存放項目的文件夾,如件夾,如H:C#2005ch8Proj8_3Proj8_3,其中包含有本項目的,其中包含有本項目的C#文件。為文件。為了能夠執行了能夠執行csc程序,通過程序,通過path設置路徑,即在命令行方式中輸入以下命令:設置路徑,即在命令行方式中輸入以下命令:path C:WindowsMicrosoft.NETFrameworkv2.0.50727 常用的編譯命令如下:常用的編譯命令如下: (1)csc/t

31、arget:library 模塊名模塊名 該命令使編譯器創建一個動態鏈接庫(該命令使編譯器創建一個動態鏈接庫(DLL)而不是一個可執行文件)而不是一個可執行文件(EXE)。)。 (2)csc/reference:filename 該命令導致編譯器將指定文件中的該命令導致編譯器將指定文件中的public類型信息導入到當前項目中,從類型信息導入到當前項目中,從而可以從指定的程序集文件引用元數據。而可以從指定的程序集文件引用元數據。filename包含程序集清單的文件的包含程序集清單的文件的名稱。若要導入多個文件,請為每個文件包括一個單獨的名稱。若要導入多個文件,請為每個文件包括一個單獨的/refe

32、rence選項。選項。同樣通過添加代碼文件模板向其中添加一個同樣通過添加代碼文件模板向其中添加一個SomeSports.cs文件,該文件的內容如下:文件,該文件的內容如下:using System;public class Basketball : Sportpublic Basketball()/籃球類籃球類name = 籃球籃球; public override string GetDuration()return 共節,每節分鐘共節,每節分鐘; public override string GetName()return name; public class Hockey : Sport

33、/曲棍球類曲棍球類public Hockey()name = 曲棍球曲棍球; public override string GetDuration()return 兩個半場,各分鐘兩個半場,各分鐘; public override string GetName()return name; public class Football : Sport/足球類足球類public Football()name = 足球足球; public override string GetDuration()return 兩個半場,各分鐘兩個半場,各分鐘; public override string GetNa

34、me()return name; 在命令行方式下使用以下命令生成在命令行方式下使用以下命令生成SomeSports.dll文件:文件:csc/target:library /reference:Sport.dll SomeSports.cs這樣就生成兩個動態鏈接庫文件這樣就生成兩個動態鏈接庫文件Sport.dll和和SomeSports.dll。現要在現要在Program類類Main中設計相應代碼,根據用戶選擇的體育中設計相應代碼,根據用戶選擇的體育項目輸出相應的比賽時間。項目輸出相應的比賽時間。解:解:由于在設計由于在設計Program.cs程序時,提供的程序時,提供的Sport.dll和和

35、SomeSports.dll都是動態鏈接庫,不知道其中每個類是如何都是動態鏈接庫,不知道其中每個類是如何聲明的,只知道聲明的,只知道GetName()和和GetDuration()兩個方法的功能,兩個方法的功能,為此采用反射技術。設計為此采用反射技術。設計Program.cs程序如下:程序如下:using System;using System.Reflection;namespace Proj8_3 class Programstatic void Main(string args)int i, j; if (args.GetLength(0) 1) /命令行輸入的參數不正確命令行輸入的參數

36、不正確Console.WriteLine(用法用法:Program dll庫名庫名); else Assembly assembly=Assembly.LoadFrom(args0); /獲取程序集對象獲取程序集對象 Type types = assembly.GetTypes(); Console.WriteLine(assembly.GetName().Name + 包含的項目名如下包含的項目名如下:);for (i = 0; i types.GetLength(0); +i)Console.WriteLine(r + i + : + typesi.Name);i = types.Leng

37、th - 1; Console.Write(請選擇請選擇(0- + i + ):); j = Convert.ToInt32(Console.ReadLine(); Console.WriteLine(); if (typesj.IsSubclassOf(typeof(Sport) /若若typesj是是Sport的子類的子類 ConstructorInfo ci = typesj.GetConstructor(new Type0); Sport sport = (Sport)ci.Invoke(new Object0); /創建創建sport對象對象 Console.WriteLine(sp

38、ort.GetName()+比賽時間比賽時間:+ sport.GetDuration(); else Console.WriteLine(typesj.Name + 不屬于指定的體育項目不屬于指定的體育項目); 在命令行中輸入以下命令在命令行中輸入以下命令Program.exe文件:文件:csc/reference:Sport.dll Program.cs在命令行中輸入以下命令執行在命令行中輸入以下命令執行Program.exe:Program SomeSports.dll程序的一次執行結果如圖程序的一次執行結果如圖13.3所示,在出現各種提示所示,在出現各種提示后輸入后輸入2,輸出足球的比賽

39、時間。,輸出足球的比賽時間。.dll只需知道類和方法,可只需知道類和方法,可以通過反射技術使用它。以通過反射技術使用它。以前我們必須知道一個類的完整定義,才可以使用以前我們必須知道一個類的完整定義,才可以使用這個類。這個類。采用反射技術:采用反射技術:13.3 多線程程序設計多線程程序設計13.3.1 多線程的概述多線程的概述當一個程序開始運行時,它就是一個進程。當一個程序開始運行時,它就是一個進程。進程所指包括執行中的程序和程序所使用到的內存和進程所指包括執行中的程序和程序所使用到的內存和系統資源。系統資源。而一個進程又是由多個線程所組成的,線程是程序中而一個進程又是由多個線程所組成的,線程

40、是程序中的一個執行流,每個線程都有自己的專有寄存器(棧指針、的一個執行流,每個線程都有自己的專有寄存器(棧指針、程序計數器等),但代碼區是共享的,即不同的線程可以程序計數器等),但代碼區是共享的,即不同的線程可以執行同樣的函數。多線程是指程序中包含多個執行流,即執行同樣的函數。多線程是指程序中包含多個執行流,即在一個程序中可以同時運行多個不同的線程來執行不同的在一個程序中可以同時運行多個不同的線程來執行不同的任務,也就是說允許單個程序創建多個并行執行的線程來任務,也就是說允許單個程序創建多個并行執行的線程來完成各自的任務。完成各自的任務。 從上圖可以看出,幾乎所有的進程都擁有兩個以上的線程。從

41、而從上圖可以看出,幾乎所有的進程都擁有兩個以上的線程。從而可以看出,線程是提供應用程序性能的重要手段之一,尤其在多核可以看出,線程是提供應用程序性能的重要手段之一,尤其在多核CPU的機器上尤為明顯。的機器上尤為明顯。 一個一個C#程序開始于一個單線程,這個單線程是被程序開始于一個單線程,這個單線程是被CLR和操作系統(也稱為和操作系統(也稱為“主線程主線程”)自動創建的,并具有多)自動創建的,并具有多線程創建額外的線程。線程創建額外的線程。 在在C#應用程序中,第一個線程總是應用程序中,第一個線程總是Main()方法,因為方法,因為第一個線程是由第一個線程是由.NET運行庫開始執行的,運行庫開

42、始執行的,Main()方法方法是是.NET運行庫選擇的第一個方法。后續的線程由應用程序運行庫選擇的第一個方法。后續的線程由應用程序在內部啟動,即應用程序可以創建和啟動新的線程。在內部啟動,即應用程序可以創建和啟動新的線程。多線程:多線程:在同一時間執行多個任務的功能,稱為多線在同一時間執行多個任務的功能,稱為多線程或自由線程。程或自由線程。多線程的優點:多線程的優點:可以同時完成多個任務;可以使程序可以同時完成多個任務;可以使程序的響應速度更快;可以讓占用大量處理時間的任務或當前的響應速度更快;可以讓占用大量處理時間的任務或當前沒有進行處理的任務定期將處理時間讓給別的任務;可以沒有進行處理的任

43、務定期將處理時間讓給別的任務;可以隨時停止任務;可以設置每個任務的優先級以優化程序性隨時停止任務;可以設置每個任務的優先級以優化程序性能。能。多線程的缺點:多線程的缺點:對資源的共享訪問可能造成沖突(對對資源的共享訪問可能造成沖突(對共享資源的訪問進行同步或控制)共享資源的訪問進行同步或控制) ;程序的整體運行速度;程序的整體運行速度減慢等等。減慢等等。13.3.2 線程命名空間線程命名空間線程命名空間是線程命名空間是System.Threading,它提供了多線程,它提供了多線程程序設計的類和接口等,用以執行諸如創建和啟動線程、程序設計的類和接口等,用以執行諸如創建和啟動線程、同步多個線程、

44、掛起線程和中止線程等任務。其中有關線同步多個線程、掛起線程和中止線程等任務。其中有關線程方面的類如下:程方面的類如下:l Thread類:用于創建并控制線程、設置其優先級并獲取其狀類:用于創建并控制線程、設置其優先級并獲取其狀態。態。l Monitor類:提供同步對對象的訪問的機制。類:提供同步對對象的訪問的機制。l Mutex類:一個同步基元,也可用于進程間同步。類:一個同步基元,也可用于進程間同步。l ThreadAbortException類:在對類:在對Abort方法進行調用時引發方法進行調用時引發的異常。無法繼承此類。的異常。無法繼承此類。l ThreadInterruptedExc

45、eption類:中斷處于等待狀態的類:中斷處于等待狀態的Thread時引發的異常。時引發的異常。l ThreadStartException類:當基礎操作系統線程已啟動但該類:當基礎操作系統線程已啟動但該線程尚未準備好執行用戶代碼前,托管線程中出現錯誤,則線程尚未準備好執行用戶代碼前,托管線程中出現錯誤,則會引發異常。會引發異常。l ThreadStateException類:當類:當Thread處于對方法調用無效的處于對方法調用無效的ThreadState時引發的異常。時引發的異常。13.3.3 Thread類及其應用類及其應用1. Thread類類Thread類是最重要的線程類。類是最重要

46、的線程類。屬性屬性說明說明CurrentThread獲取當前正在運行的線程獲取當前正在運行的線程IsAlive獲取一個值,該值指示當前線程的執行狀態獲取一個值,該值指示當前線程的執行狀態IsBackground獲取或設置一個值,該值指示某個線程是否為后臺線程獲取或設置一個值,該值指示某個線程是否為后臺線程Name獲取或設置線程的名稱獲取或設置線程的名稱Priority獲取或設置一個值,該值指示線程的調度優先級獲取或設置一個值,該值指示線程的調度優先級ThreadState獲取一個值,該值包含當前線程的狀態獲取一個值,該值包含當前線程的狀態方法方法說明說明Abort在調用此方法的線程上引發在調用

47、此方法的線程上引發ThreadAbortException,以開始終止此線,以開始終止此線程的過程。調用此方法通常會終止線程程的過程。調用此方法通常會終止線程Interrupt中斷處于等待、休眠或聯接狀態的線程中斷處于等待、休眠或聯接狀態的線程Join阻塞調用線程,直到某個線程終止時為止。阻塞調用線程,直到某個線程終止時為止。t.Join()可以理解為把線程可以理解為把線程t放到當前位置來執行放到當前位置來執行,只有只有t結束以后才會執行結束以后才會執行t.Join()以后的代碼以后的代碼 Resume繼續已掛起的線程繼續已掛起的線程Sleep將當前線程阻塞指定的毫秒數將當前線程阻塞指定的毫秒

48、數Start使線程得以按計劃執行使線程得以按計劃執行Suspend掛起線程,或者如果線程已掛起,則不起作用。掛起線程,或者如果線程已掛起,則不起作用。2. 創建和啟動新線程創建和啟動新線程應用程序執行時,將創建新的應用程序域。當執行環應用程序執行時,將創建新的應用程序域。當執行環境調用應用程序的入口點(境調用應用程序的入口點(Main方法)時,將創建應用程方法)時,將創建應用程序的主線程。主線程以外的線程一般稱為序的主線程。主線程以外的線程一般稱為工作線程工作線程。Thread類的主要構造函數如下:類的主要構造函數如下:(1)public Thread(ThreadStart start)其中

49、,參數其中,參數start為為ThreadStart委托,它表示此線程開委托,它表示此線程開始執行時要調用的方法。始執行時要調用的方法。(2)public Thread(ParameterizedThreadStart start)其中,參數其中,參數start為為ParameterizedThreadStart委托,表委托,表示此線程開始執行時要調用的方法。它表示初始化示此線程開始執行時要調用的方法。它表示初始化Thread類的新實例,并指定允許對象在線程啟動時傳遞給線程的類的新實例,并指定允許對象在線程啟動時傳遞給線程的委托。委托。例如,有以下類:例如,有以下類:class MyClass

50、/聲明包含方法的類聲明包含方法的類public void method1()/不帶參數的方法不帶參數的方法method1public void method2(object data) /帶參數的方法帶參數的方法method2采用靜態方式創建和啟動工作線程的過程如下:采用靜態方式創建和啟動工作線程的過程如下:MyClass obj = new MyClass();/創建創建MyClass的實例的實例Thread workth1 = new Thread(obj.method1);/創建一個工作線程創建一個工作線程workth1workth1.Start();/啟動工作線程啟動工作線程workt

51、h1Thread workth2 = new Thread(obj.method1);/創建一個工作線程創建一個工作線程workth2workth1.Start(10);/啟動工作線程啟動工作線程workth2,其中,其中10為實參為實參delegate void deletype1();/聲明委托類型聲明委托類型deletype1delegate void deletype2(object obj);/聲明委托類型聲明委托類型deletype2deletype1 mydele1;/定義委托變量定義委托變量mydele1deletype2 mydele2;/定義委托變量定義委托變量mydele

52、2MyClass a = new MyClass();/創建創建MyClass類的實例類的實例mydele1 = new deletype1(a.method1);mydele2 = new deletype2(a.method2);Thread workth1 = new Thread(new ThreadStart(mydele1);/創建一個工作線程創建一個工作線程workth1workth1.Start();/啟動工作線程啟動工作線程workth1Thread workth2 = new Thread(new ParameterizedThreadStart(mydele2); /創建

53、一個工作線程創建一個工作線程workth2workth2.Start(10);/啟動工作線程啟動工作線程workth2,其中,其中10為實參為實參采用委托方式創建和啟動工作線程的過程如下:采用委托方式創建和啟動工作線程的過程如下:3. 暫停線程暫停線程一旦線程已啟動,就可以調用其方法來更改它的狀態。一旦線程已啟動,就可以調用其方法來更改它的狀態。例如,例如,通過調用通過調用Thread.Sleep()可以使線程暫停一段時間可以使線程暫停一段時間(以毫秒為單位)。其使用語法格式如下:(以毫秒為單位)。其使用語法格式如下:Thread.Sleep(n);其中其中n為掛起的毫秒數,即線程保持鎖定狀態

54、的毫秒數。為掛起的毫秒數,即線程保持鎖定狀態的毫秒數。如果使用參數如果使用參數Infinite調用調用Sleep,則會導致線程休眠,則會導致線程休眠,直至調用直至調用Interrupt的另一個線程將其喚醒為止。的另一個線程將其喚醒為止。 Thread.Sleep(Timeout.Infinite);4. 中斷線程中斷線程Interrupt()Interrupt()方法會將目標線程從其可能處于的任何等方法會將目標線程從其可能處于的任何等待狀態中喚醒,并導致引發待狀態中喚醒,并導致引發ThreadInterruptedException異異常。常。通過對被阻止的線程調用通過對被阻止的線程調用Int

55、errupt()方法可以中斷正方法可以中斷正在等待的線程,從而使該線程脫離造成阻止的調用。在等待的線程,從而使該線程脫離造成阻止的調用。 線程應該捕獲線程應該捕獲ThreadInterruptedException異常并執行異常并執行任何適當的操作以繼續運行。如果線程忽略該異常,則運任何適當的操作以繼續運行。如果線程忽略該異常,則運行庫將捕獲該異常并停止該線程。行庫將捕獲該異常并停止該線程。5. 銷毀線程銷毀線程Abort()Abort()方法用于永久地停止托管線程。調用方法用于永久地停止托管線程。調用Abort時,時,公共語言運行庫在目標線程中引發公共語言運行庫在目標線程中引發ThreadA

56、bortException,目標線程可捕捉此異常。目標線程可捕捉此異常。Abort()方法不直接導致線程中止,因為目標線程可捕捉方法不直接導致線程中止,因為目標線程可捕捉ThreadAbortException并在并在finally塊中執行任意數量的代碼。塊中執行任意數量的代碼。 如果需要等待線程結束,可調用如果需要等待線程結束,可調用Join()方法。方法。Thread.Join()是一種模塊化調用,它在線程實際停止執行之是一種模塊化調用,它在線程實際停止執行之前,或可選超時間隔結束之前不會返回。等待對前,或可選超時間隔結束之前不會返回。等待對Join()方法方法的調用的線程可由其他線程調用

57、的調用的線程可由其他線程調用Interrupt()來中斷。來中斷。注意:一旦線程被中止,它將無法重新啟動。如果線注意:一旦線程被中止,它將無法重新啟動。如果線程已經在中止,則不能通過程已經在中止,則不能通過Start()來啟動線程。來啟動線程。線程狀態關系圖線程狀態關系圖 WaitSleepJoin:線程因為調用了:線程因為調用了Wait(),Sleep()或或Join()等方法處于封鎖狀態等方法處于封鎖狀態 Stopped:線程已經被停止:線程已經被停止 Running:線程正:線程正在正常運行在正常運行 AbortRequested:線:線程的程的Thread.Abort()方方法已被調用

58、,但是線法已被調用,但是線程還未停止程還未停止 Aborted:線程已停止:線程已停止 InterruptSleep,Joinusing System; using System.Threading;class ThreadTest static void Main() Thread t = new Thread (WriteY); t.Start(); / Run WriteY on the new thread while (true) Console.Write (x); / Write x forever static void WriteY() while (true) Consol

59、e.Write (y); / Write y forever 主線程創建了一個新線程主線程創建了一個新線程“t”,它運行了一個重復打,它運行了一個重復打印字母印字母y的方法,同時主線程重復打印字母的方法,同時主線程重復打印字母“x”。CLR分分配每個線程到它自己的內存堆棧上,來保證局部變量的分配每個線程到它自己的內存堆棧上,來保證局部變量的分離運行。離運行。 【例【例13.4】 分析以下程序的執行結果。分析以下程序的執行結果。using System;using System.Threading;/新增引用新增引用namespace Proj13_4public class Apublic v

60、oid fun()/定義類定義類A的方法的方法while (true) Console.WriteLine(工作線程工作線程:正在執行正在執行A.fun方法方法.); ;public class Programpublic static void Main() Console.WriteLine(主線程啟動主線程啟動.);A a = new A();/創建創建A類的實例類的實例 Thread workth = new Thread(new ThreadStart(a.fun); /創建一個線程,使之執行創建一個線程,使之執行A類的類的fun()方法方法 Console.WriteLine(工作

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論