新聞中心
2000年6月,Microsoft發(fā)布了一種新的程序設計語言——C#。C#是一種現(xiàn)代的,面向對象的語言,它使開發(fā)人員能夠在Microsoft .NET框架上快速建立廣泛的應用。C#支持建立自由線程(free-threaded)的應用,多個線程可以訪問同一套共享數(shù)據(jù)。

我們提供的服務有:網(wǎng)站設計制作、成都網(wǎng)站設計、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認證、交口ssl等。為1000+企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務,是有科學管理、有技術的交口網(wǎng)站制作公司
C#多線程應用實例程序說明
本文的實例程序包括一個列表框、三個按鈕。程序使用一個新的線程來運行一個后臺處理,結果在列表框中顯示。按鈕button1啟動一個計算平方的線程。按鈕button2停止后臺處理線程。按鈕button3退出程序。程序運行情況如圖1所示。
C#多線程應用 圖1
使用線程
首先創(chuàng)建運行在新線程上的后臺任務。表1所示的代碼執(zhí)行一個相當長的運行處理----一個無限循環(huán)。
表1、后臺處理程序
- private void BackgroundProcess()
- {
- int i= 1;
- while(true)
- {
- // 向列表框增加一個項目
- listBox1.Items.Add("Iterations: " + i.ToString ());
- i ++;
- Thread.Sleep(2000); // 指定線程休眠的時間
- }
- }
這段代碼無限循環(huán),每次執(zhí)行時在列表框中加入一個項目。
在規(guī)定好一個工作的處理代碼以后,就需要將這段代碼分配給一個線程,并且啟動它。為此需要使用線程對象(Thread object),它是.NET架構類中System.Threading命名空間的一部分。在實例化一個新的線程類時,需要把在線程類構造器中執(zhí)行的代碼塊的一個引用傳送給該實例。表2所示的代碼創(chuàng)建一個新的線程對象,并且將BackgroundProcess的一個引用傳送給該對象。
表2、線程的使用
- Thread t1,t2; // 說明為窗體類成員
- t1 = new Thread(new ThreadStart(BackgroundProcess));
- t1.Start(); // 以上2行放置在窗體的load事件中
ThreadStart表示在線程上執(zhí)行的方法,這里是一個到BackgroundProcess方法的委派對象。在C#中,一個委派是一個類型安全、面向對象的函數(shù)指針。在實例化該線程后,可以通過調用線程的Start()方法來開始執(zhí)行代碼。
控制線程
在線程啟動以后,可以通過調用線程對象的方法來控制線程的狀態(tài)??梢酝ㄟ^調用Thread.Sleep方法來暫停一個線程的執(zhí)行,這個方法可以接收一個整型值,用來決定線程休眠的時間。對于本文的實例程序,為了讓列表項目增加的速度變慢,在其中放入了一個Sleep方法的調用。
可以通過調用Thread.Sleep(System.Threading.Timeout.Infinite)來讓線程進入休眠狀態(tài),但是,這個調用的休眠時間是不確定的。要中斷這個休眠,可以調用Thread.Interrupt方法。
通過調用Thread.Suspend方法可以掛起線程。掛起可以暫停一個線程,直到另一個線程調用Thread.Resume為止。休眠和掛起的區(qū)別是,掛起并不立刻讓線程進入一個等待的狀態(tài),線程并不會掛起,直到.NET runtime認為現(xiàn)在已經(jīng)是一個安全的地方來掛起它了,而休眠則會立刻讓線程進入一個等待的狀態(tài)。
表3、停止線程的執(zhí)行
- private void button2_Click
- (object sender, System.EventArgs e)
- { t1.Abort(); }
Thread.Abort方法可以停止一個線程的執(zhí)行。本文的實例程序通過加入一個按鈕button2來停止后臺處理,在事件處理程序中調用了Thread.Abort方法,如表3所示。
這就是多線程的強大之處。用戶界面的響應很快,因為用戶界面運行在一個單獨的線程中,而后臺的處理運行在另外一個線程中。在用戶按下按鈕button2時,就會馬上得到響應,并且停止后臺處理。
通過多線程程序傳送數(shù)據(jù)
在實際工作中,還需要使用到多線程的許多復雜特性。其中一個問題就是如何將程序的數(shù)據(jù)由線程類的構造器傳入或者傳出。對于放到另外一個線程中的過程,既不能傳參數(shù)給它,也不能由它返回值,因為傳入到線程構造器的過程是不能擁有任何參數(shù)或者返回值的。為了解決這個問題,可以將過程封裝到一個類中,這樣,方法的參數(shù)就可使用類中的字段。
本文給出了一個簡單的例子,計算一個數(shù)的平方。為了在一個新的線程中使用這個過程,將它封裝到一個類中,如表4所示。
使用表5所示的代碼在一個新的線程上啟動CalcSquare過程。
表4、計算一個數(shù)的平方 表5、在一個新的線程上啟動CalcSquare過程
- public class SquareClass
- {
- public double Value;
- public double Square;
- public void CalcSquare()
- {
- Square = Value * Value;
- }
- } private void button1_Click(object sender, System.EventArgs e)
- {
- SquareClass oSquare =new SquareClass();
- t2 = new Thread(new ThreadStart(oSquare.CalcSquare));
- oSquare.Value = 30;
- t2.Start();
- }
在上述例子中,線程啟動后,并沒有檢查類中的square值,因為即使調用了線程的start方法,也不能確保其中的方法馬上執(zhí)行完。要從另一個線程中得到需要的值,有幾種方法,其中一種方法就是在線程完成的時候觸發(fā)一個事件。表6所示的代碼為SquareClass加入了事件聲明。
表6、為SquareClass加入事件聲明
- public delegate void EventHandler(double sq); // 說明委派類型
- public class SquareClass
- {
- public double Value;
- public double Square;
- public event EventHandler ThreadComplete; // 說明事件對象
- public void CalcSquare()
- {
- Square = Value * Value;
- // 指定事件處理程序
- ThreadComplete+=new EventHandler(SquareEventHandler);
- if( ThreadComplete!=null)ThreadComplete(Square); // 觸發(fā)事件
- }
- public static void SquareEventHandler(double Square ) // 定義事件處理程序
- { MessageBox.Show(Square.ToString ()); }
- }
對于這種方法,要注意的是事件處理程序SquareEventHandler運行在產(chǎn)生該事件的線程t2中,而不是運行在窗體執(zhí)行的線程中。
同步線程
在線程的同步方面,C#提供了幾種方法。在上述計算平方的例子中,需要與執(zhí)行計算的線程同步,以便等待它執(zhí)行完并且得到結果。另一個例子是,如果在其它線程中排序一個數(shù)組,那么在使用該數(shù)組前,必須等待該處理完成。為了實現(xiàn)同步,C#提供了lock聲明和Thread.Join方法。
lock聲明
表7、使用lock聲明
- public void CalcSquare1()
- {
- lock( typeof(SquareClass))
- {
- Square = Value * Value;
- }
- }
lock可以得到一個對象引用的***鎖,使用時只要將該對象傳送給lock就行了。通過這個***鎖,可以確保多個線程不會訪問共享的數(shù)據(jù)或者在多個線程上執(zhí)行的代碼。要得到一個鎖,可以使用與每個類關聯(lián)的System.Type對象。System.Type對象可以通過使用typeof運算得到,如表7所示。
Thread.Join方法
表8、使用Thread.Join方法
- private void button1_Click(object sender, System.EventArgs e)
- {
- SquareClass oSquare =new SquareClass();
- t2 = new Thread(new ThreadStart(oSquare.CalcSquare));
- oSquare.Value = 30;
- t2.Start();
- if( t2.Join (500) )
- {
- MessageBox.Show(oSquare.Square.ToString ());
- }
- }
Thread.Join方法可以等待一個特定的時間,直到一個線程完成。如果該線程在指定的時間內完成了,Thread.Join將返回True,否則它返回False。在上述平方的例子中,如果不想使用觸發(fā)事件的方法,可以調用Thread.Join的方法來確定計算是否完成了。代碼如表8所示。
結論
本文通過一個實例程序說明了C#多線程應用和控制方法,探討了如何通過多線程程序傳送數(shù)據(jù)和線程的同步問題。根據(jù)本文的分析可知,在C#中,使用線程是很簡單的。C#支持建立自由線程的應用,提高了資源的利用率,程序的響應速度也得到了改善。當然也帶來了數(shù)據(jù)傳送和線程同步等問題。
【編輯推薦】
- C#實現(xiàn)多語言界面程序的方法介紹
- 介紹C#構造函數(shù)的使用方法
- C#多態(tài)性的概念及其應用
- 淺析C# treeview控件的使用方法
- 總結C#獲取當前路徑的7種方法
本文題目:探討C#多線程應用的相關問題
瀏覽路徑:http://m.fisionsoft.com.cn/article/cdpepoo.html


咨詢
建站咨詢
