您好,登錄后才能下訂單哦!
本篇內容主要講解“C#線程的作用是什么及怎么創建”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“C#線程的作用是什么及怎么創建”吧!
線程 被定義為程序的執行路徑。每個線程都定義了一個獨特的控制流。如果您的應用程序涉及到復雜的和耗時的操作,那么設置不同的線程執行路徑往往是有益的,每個線程執行特定的工作。
線程是輕量級進程。一個使用線程的常見實例是現代操作系統中并行編程的實現。使用線程節省了 CPU 周期的浪費,同時提高了應用程序的效率。
到目前為止我們編寫的程序是一個單線程作為應用程序的運行實例的單一的過程運行的。但是,這樣子應用程序同時只能執行一個任務。為了同時執行多個任務,它可以被劃分為更小的線程。
線程生命周期開始于 System.Threading.Thread 類的對象被創建時,結束于線程被終止或完成執行時。
下面列出了線程生命周期中的各種狀態:
未啟動狀態:當線程實例被創建但 Start 方法未被調用時的狀況。
就緒狀態:當線程準備好運行并等待 CPU 周期時的狀況。
不可運行狀態:下面的幾種情況下線程是不可運行的:
已經調用 Sleep 方法
已經調用 Wait 方法
通過 I/O 操作阻塞
死亡狀態:當線程已完成執行或已中止時的狀況
在C# 語言中使用線程時首先需要創建線程,在使用 Thread 類的構造方法創建其實例時,需要用到 ThreadStart 委托或者 ParameterizedThreadStart 委托創建 Thread 類的實例。ThreadStart 委托只能用于無返回值、無參數的方法,而ParameterizedThreadStart 委托則可以用于帶參數的方法。
ThreadStar的方式創建
例子:
using System; using System.Threading; namespace MultithreadingApplication { class ThreadCreationProgram { //線程函數 public static void CallToChildThread() { Console.WriteLine("Child thread starts"); } static void Main(string[] args) { //創建ThreadStart的委托實例 ThreadStart childref = new ThreadStart(CallToChildThread); Console.WriteLine("In Main: Creating the Child thread"); //創建Thread類的實例 Thread childThread = new Thread(childref); childThread.Start(); //開始一個線程 Console.ReadKey(); } } }
運行結果:
ParameterizedThreadStart
例子:
using System; using System.Threading; namespace MultithreadingApplication { class Program { static void Main(string[] args) { //創建一個線程委托對象 ParameterizedThreadStart pts = new ParameterizedThreadStart(PrintEven); Console.WriteLine("In Main: Creating the Child thread"); // 創建一個線程對象 Thread childThread = new Thread(pts); childThread.Start(10); Console.ReadKey(); } //線程跑的函數 //打印0~n中的偶數 private static void PrintEven(Object n) { Console.WriteLine("Child thread started"); for(int i=0; i<=(int)n; i+=2) //類型轉換 { Console.WriteLine(i); } } } }
運行結果:
using System; using System.Threading; namespace MultithreadingApplication { class ThreadCreationProgram { public static void CallToChildThread() { Console.WriteLine("Child thread starts"); int sleepfor = 5000; Console.WriteLine("Child Thread Paused for {0} seconds", sleepfor / 1000); Thread.Sleep(sleepfor); //讓線程暫停 單位毫秒 Console.WriteLine("Child thread resumes"); } static void Main(string[] args) { //創建一個線程的委托 ThreadStart childref = new ThreadStart(CallToChildThread); Console.WriteLine("In Main: Creating the Child thread"); //創建線程的實例 Thread childThread = new Thread(childref); childThread.Start(); Console.ReadKey(); } } }
運行結果:最后一行是5s后才打印出來的
/* 銷毀線程 */ using System; using System.Threading; namespace MultithreadingApplication { class ThreadCreationProgram { //委托函數 public static void CallToChildThread() { try//引起異常的語句 { Console.WriteLine("Child thread starts"); for(int counter = 0; counter <= 10; counter++) { Thread.Sleep(500); Console.WriteLine(counter); } Console.WriteLine("Child Thread Completed"); } catch(ThreadAbortException e)//錯誤處理代碼 { Console.WriteLine("Thread Abort Exception"); } finally //執行的語句 { Console.WriteLine("Could't catch the Thread Exception"); } } static void Main(string[] args) { //創建一個線程的委托實例 ThreadStart childref = new ThreadStart(CallToChildThread); Console.WriteLine("In Main: Creating the Child thread"); //創建一個線程對象 Thread childThread = new Thread(childref); childThread.Start(); //主線程休眠 Thread.Sleep(2000); Console.WriteLine("In Main:Aborting the Child thread"); //在調用此方法的線程上引發ThreadAbortException,以開始終止此線程的過程。 //調用此方法通常會終止線程 childThread.Abort(); Console.ReadKey(); } } }
運行結果:
在C#中線程的優先級使用線程的Priority屬性設置即可,默認的優先級是Normal。在設置優先級后,優先級高的線程將優先執行。優先級的值通關ThreadPriority枚舉類型來設置,從低到高分別為Lowest 、BelowNormal、Normal、 AboveNormal、 Highest。
例子:
using System; using System.Threading; namespace MultithreadingApplication { class Program { //奇數 public static void PrintOdd() { Console.WriteLine("List of odd numbers:"); for (int i = 1; i <= 100; i += 2) { Console.Write(i + " "); } Console.WriteLine(); } //偶數 public static void PrintEven() { Console.WriteLine("List of even numbers: "); for(int i = 0; i<=100; i+=2) { Console.Write(i + " "); } Console.WriteLine(); } static void Main(string[] args) { //創建線程的委托1 ThreadStart childref1 = new ThreadStart(PrintEven); Console.WriteLine("In Main: Creating the Child1 thread"); //創建線程1的實例 Thread childThread1 = new Thread(childref1); //設置打印偶數優先級為最低 childThread1.Priority = ThreadPriority.Lowest; //創建線程的委托2 ThreadStart childref2 = new ThreadStart(PrintOdd); Console.WriteLine("In Main: Creating the Child2 thread"); //創建線程2的實例 Thread childThread2 = new Thread(childref2); //設置打印奇數優先級為最高 childThread2.Priority = ThreadPriority.Highest; childThread1.Start();//偶數 低 childThread2.Start();//奇數 高 Console.ReadKey(); } } }
運行的結果:
第一次運行:
第二次:
第三次:
第四次:
小結:
從上面的運行效果可以看出,由于輸岀奇數的線程的優先級高于輸出偶數的線程,所以在輸出結果中優先輸出奇數的次數會更多。
此外,每次輸出的結果也不是固定的。通過優先級是不能控制線程中的先后執行順序的,只能是優先級高的線程優先執行的次數多而已。
線程狀態控制的方法包括暫停線程 (Sleep)、中斷線程 (Interrupt)、掛起線程 (Suspend)、喚醒線程 (Resume)、終止線程 (Abort)。
sleep 方法能控制線程的暫停時間,從而改變多個線程之間的先后順序,但每次調用線程的結果是隨機的。線程同步的方法是將線程資源共享,允許控制每次執行一個線程,并交替執行每個線程。在 C# 語言中實現線程同步可以使用 lock 關鍵字和 Monitor 類、Mutex 類來解決。對于線程同步操作最簡單的一種方式就是使用 lock 關鍵字,通過 lock 關鍵字能保證加鎖的線程只有在執行完成后才能執行其他線程。
lock的語法如下
lock(object) { //臨界區代碼 }
這里 lock 后面通常是一個 Object 類型的值,也可以使用 this 關鍵字來表示。
最好是在 lock 中使用私有的非靜態或負變量或私有的靜態成員變量,即使用 Private 或 Private static 修飾的成員。
例如:
private Object obj = new Object(); lock (obj) { //臨界區代碼 }
一個更具體的實例
using System; using System.Threading; namespace MultithreadingApplication { class Program { //打印偶數 public void PrintEven() { //lock上鎖保證執行完該線程才跑其他線程 lock(this) { for(int i=0; i<=10; i+=2) { //獲取當前線程的名字 Console.WriteLine(Thread.CurrentThread.Name + "--" + i); } } } //打印奇數 public void PrintOdd() { lock (this) { for (int i = 1; i <= 10; i += 2) { Console.WriteLine(Thread.CurrentThread.Name + "--" + i); } } } static void Main(string[] args) { //因為下面要用到program類中的非靜態函數,所以先創建該類對象 Program program = new Program(); //創建線程1的托管 ThreadStart ts1 = new ThreadStart(program.PrintOdd); //創建線程1 Thread t1 = new Thread(ts1); t1.Name = "打印奇數的線程"; //跑線程1 t1.Start(); ThreadStart ts2 = new ThreadStart(program.PrintEven); Thread t2 = new Thread(ts2); t2.Name = "打印偶數的線程"; t2.Start(); } } }
運行結果:
和lock用法本質是一樣的,使用Monitor類鎖定資源的語法如下:
Monitor.Enter(object); try { //臨界區代碼 } finally { Monitor.Exit(object); }
這里的object與lock中的object一樣。
具體例子
sing System; using System.Threading; namespace MultithreadingApplication { class Program { public void PrintEven() { //在指定對象上獲取排它鎖 Monitor.Enter(this); try//臨界區代碼 { for(int i=0; i<=10; i+=2) { Console.WriteLine(Thread.CurrentThread.Name + "--" + i); } } finally { //釋放指定對象的排它鎖 Monitor.Exit(this); } } public void PrintOdd() { Monitor.Enter(this); try { for(int i=1; i<=10; i+=2) { Console.WriteLine(Thread.CurrentThread.Name + "--" + i); } } finally { Monitor.Exit(this); } } static void Main(string[] args) { //下面創建委托對象時調用的是Program類的非靜態方法, //所先創建一個program對象 Program program = new Program(); //實例化一個委托 ThreadStart ts1 = new ThreadStart(program.PrintOdd); //創建一個線程 Thread t1 = new Thread(ts1); //給線程名字賦值 t1.Name = "打印奇數的線程"; //開跑線程 t1.Start(); ThreadStart ts2 = new ThreadStart(program.PrintEven); Thread t2 = new Thread(ts2); t2.Name = "打印偶數的線程"; t2.Start(); } } }
運行結果:
Monitor 類的用法雖然比 lock 關鍵字復雜,但其能添加等待獲得鎖定的超時值,這樣就不會無限期等待獲得對象鎖。使用 TryEnter() 方法可以給它傳送一個超時值,決定等待獲得對象鎖的最長時間。
使用 TryEnter() 方法設置獲得對象鎖的時間的語法如下:
Monitor.TryEnter(object, 毫秒數 );
Mutex類也是用于線程同步操作的類,當多個線程同時訪問一個資源識保證只有一個線程訪問資源。在Mutex類中,WaitOne()方法用于等待資源被釋放,ReleaseMutex()方法用于釋放資源。 WaitOne()方法在等待ReleMutex()方法執行后才會結束。
例子:
using System; using System.Threading; namespace MultithreadingApplication { class Program { //創建一個鎖對象 private static Mutex mutex = new Mutex(); public static void PakingSpace(object num) { if(mutex.WaitOne())//等待釋放資源,當前資源沒調用時為true { try { Console.WriteLine("車牌號{0}的車駛入!", num); Thread.Sleep(1000);//線程休眠一秒 } finally { Console.WriteLine("車牌號{0}的車離開!", num); mutex.ReleaseMutex(); //釋放鎖資源 } } } static void Main(string[] args) { //創建一個委托帶參數的 ParameterizedThreadStart ts = new ParameterizedThreadStart(PakingSpace); //創建一個線程 Thread t1 = new Thread(ts); t1.Start("A123456"); Thread t2 = new Thread(ts); t2.Start("B00000"); Console.ReadKey(); } } }
運行結果:
到此,相信大家對“C#線程的作用是什么及怎么創建”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。