程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 漫談多線程(上),漫談多線程(

漫談多線程(上),漫談多線程(

編輯:C#入門知識

漫談多線程(上),漫談多線程(


hey,you guys.

     好久不見了,最近忙著學習英文,處理一些雜事,所以沒有來得及更新博客。公司目前沒活,比較清閒。所以,有時間研究了一下<叩響C#之門>。據說作者是一位40多歲的初中數學老師,自學C#。40多歲的人自學編程,這份毅力很令人敬佩。這本書寫的,是C#語言的基礎知識。作者講解的很清楚,讀後很受益。很多之前一知半解,甚至一點都不懂得基礎原理,現在豁然開朗。就像孔子所說:“朝聞道,夕死可矣。”這本書,真的適合初級.NET程序員讀一下,真的很有幫助的。好了,書歸正傳,來開始我們今天的學習吧。

   多線程這塊,在.NET中屬於深層次的技術了。今天,我們就來學習學習多線程的知識吧。

線程的概念

大家平時使用電腦,可以一邊聽音樂,一邊下載電影,一邊浏覽網頁。那麼電腦它是如何滿足用戶這種需求呢?原來操作系會創建三個應用程序,通過應用程序來執行用戶的操作。每個應用程序被看作一條連續的指令流,CPU一條條執行這些指令流。但是早一些的電腦CPU不允許同一時間執行多條指令流,那麼電腦又是如何做的呢?操作系統創建三個應用程序的同時,也創建了三個進程(Process)。進程不但包括了應用程序的指令流,還包括了運行應用程序所需的內存、寄存器等等。操作系統通過進程來執行應用程序。我們可以把進程看作是執行路線。操作系統 通過”時間片輪轉”來輪流執行這些進程。所以,宏觀上進程是並發執行的,在微觀上是交替進行的。也就是說,電腦並不是同時滿足聽音樂、下載電影、浏覽網頁的,CPU是交替執行的,只不過交替時間很短暫,我們感覺不到。我們設想這樣一個場景,一個網頁播放Flash的同時,網頁上還有一個文本框,來接受用戶的輸入。這個網頁需要一邊播放Flash,一邊接受用戶的輸入。Note (個人理解,CPU執行這個網頁的進程指令,同時這個進程還要執行播放Flash、接受用戶輸入這兩個指令)。如果是以前,我們需要很復雜的一段代碼來實現這個需求。但是多線程(Multi-Threading)技術的出現,就可以很容易的實現這個需求了。可以在網頁這個進程中創建兩個線程,通過這兩個線程來執行播放Flash、接受用戶輸入。我們可以把進程中的多個線程,看作是多條執行路線。一個進程中的多個線程,它們共享資源。所以,線程之間的切換要遠遠快於進程之間的切換,我們可以把線程看作是輕量級的進程(LightweightProcess)。操作系統通過調度程序來管理線程,不需程序員關心,我們只需編寫好線程即可,線程是CPU調度的基本單位。

Thread類

計算機運行某個應用程序時,會創建一個進程,進程會創建多個線程,通過線程來執行工作,我們把執行某些工作的線程稱為工作線程(Work Thread)。C#中,關於線程的處理,都是通過System.Threading命名空間下的Thread類來完成的。

Using System.Threading;   //別忘了添加引用

//聲明一個線程的代碼
Thread workThread=new Thread(entryPoint);

entryPoint:是入口方法,線程會從入口方法的第一行代碼執行。大家應該可以看出,Thread類的構造函數的參數類型是一個委托類型。也就是說entryPoint的函數的返回值、參數取決於Thread類的構造函數的委托參數決定。

//Thread類的構造函數參數的委托類型
public delegate void ThreadStart();

public delegate void ParameterizedThreadStart(object obj);

入口方法,必須是ThreadStart或ParameterizedThreadStart的委托。

那麼綜上所述,如果要創建一個線程,需要兩步.

//第一步 創建入口方法
private void EntryPoint()
{
  //線程的具體代碼
   ...........
    ...........
}

//第二步 創建線程對象
Thread workThread=new Thread(EntryPoint);

 

線程的優先級

我們工作生活中,需要處理很多事情。一般當緊的事兒需要及時處理,不當緊的事兒可放在後面處理。線程處理指令也是一樣的,也分當緊與不當緊。通過Thread類的Priority屬性來設置線程的優先級。Priority屬性是一個ThreadPriority枚舉。這個枚舉有以下5個優先等級:

Normal、AboveNormal、Highest、BelowNormal、Lowest。

我們跑一下程序來測試一下線程優先級:

            //workThread1線程
            Thread workThread1 = new Thread(delegate()
            {
                for (int i = 0; i < 100000000; i++)
                {
                    if (i % 1000000 == 0)
                    {
                        Console.Write("A");
                    }
                }
            });

            //workThread2線程
            Thread workThread2 = new Thread(delegate()
            {
                for (int i = 0; i < 100000000; i++)
                {
                    if (i % 1000000 == 0)
                    {
                        Console.Write("B");
                    }
                }
            });

            //啟動線程
            workThread1.Start();
            workThread2.Start();

運行程序,效果如下圖:

//workThread1線程 Thread workThread1 = new Thread(delegate() { for (int i = 0; i <= 500000000; i++) { if (i % 1000000 == 0) { Console.Write('A'); } } }); //workThread2線程 Thread workThread2 = new Thread(delegate() { for (int i = 0; i <= 500000000; i++) { if (i % 1000000 == 0) { Console.Write('B'); } } }); //修改Thread的優先級 workThread1.Priority = ThreadPriority.AboveNormal; workThread2.Priority = ThreadPriority.BelowNormal; //啟動線程 workThread1.Start(); workThread2.Start(); //主線程代碼 for (int i = 0; i <= 500000000; i++) { if (i % 1000000 == 0) { Console.Write('M'); } }

 

其實除了workThread1、workThread2還有一個主線程(Main Thread)。我們修改了一下主線程的代碼,以便觀察三個線程是如何交叉工作的。我們代碼中把workThread的Priority的屬性設置為高於一般(AboveNormal)、把workThread2的Priority屬性設置為低於一般(BelowNormal)。此時運行程序的效果如下圖:

static void Main(string[] args) { //workThread1線程 Thread workThread1 = new Thread(delegate() { for (int i = 0; i <= 500000000; i++) { if (i % 1000000 == 0) { Console.Write('A'); } } }); //workThread2線程 Thread workThread2 = new Thread(delegate() { for (int i = 0; i <= 50000000; i++) { if (i % 1000000 == 0) { Console.Write('B'); } } workThread1.Join(); for (int i = 0; i <= 50000000; i++) { if (i % 10000 == 0) { Console.Write('b'); } } }); //啟動線程 workThread1.Start(); workThread2.Start(); }

   我們在線程workThread2的入口方法中,調用了workThread1的join()方法,此時當程序執行到join()方法時,workThread2就會停止工作,去執行workThread1,直到workThread1執行完畢,才會接著執行workThread2。程序運行結果如下圖:

QQ Photo20140822141249

Join()方法,還可以接受一個表示毫秒的參數,當達到這個時間,不論是否執行完畢,都會退出。

線程狀態

線程一共有7種狀態,它們分別是未開始狀態(UnStarted)、運行狀態(Running)、等待睡眠插入狀態(WaitSleepJoin)、掛起請求狀態(SuspendRequested)、掛起狀態(Suspended)、中止請求狀態(AbortRequested)、中止狀態(Stopped)。大家可以通過下面這幅圖片來認識這7中狀態:

QQ Photo20140822142019

1.未開始狀態(Unstarted)

當一個線程被創建,它的狀態會變為未開始狀態(UnStarted).

2.運行狀態(Running)

當線程調用Start()方法時,線程狀態就會變為運行狀態(Ruuning)。

3.等待睡眠插入狀態(WaitSleepJoin)

當運行狀態的線程調用方法Sleep()、Join()、或Wait()時,線程狀態會變為等待睡眠插入狀態(WaitSleepJoin).此時如果調用Pulse()或Interrupt()線程狀態會變為Running狀態。

4.掛起請求狀體(SuspendRequested)

當運行狀態的線程調用方法Suspend()的時,線程狀態會變為SuspendRequested。

5.掛起狀態(Suspended)

當調用Suspend()方法時,線程不會立馬被掛起,而是會處於SuspendRequested狀態,線程會再執行幾條指令,當確保線程在一個安全的狀態下,掛起線程,線程狀態變為Suspended。調用Resume()方法可以使線程狀體變為Running狀態。

6.中止請求狀態(AbortRequested)

當處於運行狀態的線程調用方法Abort()時,線程狀態會變為AbortRequested。

7.中止狀態(Aborted)

當線程調用Abort()方法時,線程不會馬上中止,而會處於AbortRequested狀態,再執行幾條指令,當確保線程在一個安全狀態下,中止線程,線程狀態變為Stopped。


多線程上傳的概念

是這樣的。我以前寫過FTP上傳。就是用多線程做的。
 

C語言中的線程?

給你推薦一些比較好的教程吧,你應該用得著: 漫談C++ Builder多線程編程技術: www.it55.com/...5.html 用MFC編寫多線程程序實例: www.it55.com/...7.html C++寫的web服務器程序(多線程): www.it55.com/...9.html 後面兩個都是多線程的實例教程。
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved