c#Thread類多線程系列之(二)調用帶參數的函數

來源:互聯網
上載者:User
一、線程簡介

    在windows作業系統中,每個正在啟動並執行應用程式都是一個進程,一個進程可以包括一個或多個線程。線程是進程中可以並存執行的程式碼片段,它可以獨立佔用處理器時間片,同一個進程的線程可以共用進程分配的資源和空間。多線程的應用程式可以在“同一時刻”處理多項任務。

1、單線程

    預設情況下,系統為應用程式分配一個主線程,該線程執行程式中以Main方法開始和結束的代碼,該方法即是主線程的啟動進入點。

Application.Run(new LoginForm());Run方法用於當前線程上開始運行標準應用程式,並使指定表單可見。

2、多線程

    一般、需要使用者互動的軟體都必須儘可能快地對使用者的活動做出反應,但同時它又必須執行必要的計算以便儘可能將資料呈現給使用者,此時需要使用多線程。

單個應用程式也可以使用多線程: 通過網路與Web伺服器和資料庫通訊。 執行佔用大量時間的操作。 區分具有不同優先順序的任務。 使用使用者介面可以將時間分配給背景工作時仍能快速做出響應。

    建議不要在程式中使用太多線程,這樣可以最大限度減少作業系統資源的使用,提高效能。同時,跟蹤大量線程佔用大量的處理器時間,使用太多的線程式控制制代碼,可能產生許多bug。

二、線程的基本操作

    C#對線程操作,主要用到Thread類,位於System.Threading命名空間,通過使用Thread類,可以對線程建立、暫停、恢複、休眠、終止及設定優先權等操作。另,還可以使用Monitor類,Mutex類和lock關鍵字控制線程的同步執行。

1、Thread類

    線程執行的程式碼由ThreadStart委託或ParameterziedThreadStart委託指定。線程運行期間,不同時刻會處在不同狀態,總處於ThreadStart定義的一個或多個狀態。

屬性: CurrentThread:擷取當前正在啟動並執行線程 IsAlive:擷取一個值,指示當前線程的執行狀態 Name:擷取或設定線程的名稱 Priority:擷取或設定一個值,指示線程的調度優先順序 ThreadState:擷取一個值,該值包含當前線程的優先順序

方法: Abort:終止線程 Join:阻止調用線程,直到某個線程終止 ResetAbort:取消當前線程請求的Abort Resum:繼續已掛起的線程 Sleep:將當前線程阻止指定的毫秒數 Start:使線程被安排執行

2、建立線程

    建立新的線程時、需要使用Thread類,具有接受一個ThreadStart委託或ParameterizedThreadStart委託的建構函式,封裝了調用Start方法時由新線程調用的方法。建立Thread類對象後,線程對象已存在已配置,但並為建立實際線程,只有調用Start方法,才會實際建立線程。

    Start方法用來使線程被安排執行,有2中重載形式: public void Start() public void Start(object parameter)

注:一個線程已經終止,就無法通過再次調用Start方法重新啟動

3、線程掛起與恢複

    建立完一個線程並啟動後,還可以掛起、恢複、休眠或終止它。線程的掛起與恢複主要調用Thread類的Suspend方法和Resume方法實現。 Suspend方法,該方法用來掛起線程,已掛起後線程不起作用 Resume方法,繼續已掛起的線程

4、線程休眠

    由Sleep方法實現。將當前線程阻止指定的時間。Thread.Sleep(2000)

5、終止線程

    分別使用Abort方法和Join方法 Abort方法,終止線程,2種重載

        public void Abort()

        public void Abort(Object stateInfo),stateInfo表示一個對象,包含特定的資訊

  2.   Join方法,阻止調用線程,直到某個線程終止時為止

        public void Join()

        public void Join(int milliseconds Timeout) 等待線程終止毫秒數,如果線程已終止,返回為True,未終止,返回FALSE

        public void Join(TimeSpan timeout) timeout表示等待線程終止的時間量的TimeSpan如果已終止,返回TRUE,未終止,返回FALSE

三、ThreadState屬性的幾個特別屬性      如果在一個多線程程式中我們想要直到線程的運行狀態,我們就可以使用ThreadState去查看線程的運行狀態了。

Aborted:線程被中斷。線程執行過程中遇到異常被中斷了。

AbortRequested:線程的Thread.Abort()被調用但是此時的線程還未停止。

Background:線程在後台執行。

Running:線程正在正常的運行。

Stopped:線程已經被停止。

StopRequested:線程正在被要求停止。幾乎是有使用者提出停止線程的請求。

Suspended:線程已經被掛起了(可以通過Thread中常用方法的Resume進行恢複線程執行)。

SuspendRequested:線程正在要求被掛起,此時的線程還未被掛起。

Unstarted:線程還未開始。

WaitSleepJoin:線程調用了Wait()、Sleep()或Join()方法線程處於封鎖狀態。 四、C#Thread類的基本用法

1、不帶參數的線程類

通過System.Threading.Thread類可以開始新的線程,並線上程堆棧中運行靜態或執行個體方法。可以通過Thread類的的構造方法傳遞一個無參數,並且不傳回值(返回void)的委託(ThreadStart),這個委託的定義如下:

[ComVisibleAttribute(true)]

public delegate void ThreadStart()

我們可以通過如下的方法來建立並運行一個線程。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading; namespace AAAAA{    class Program    {        static void Main(string[] args)        {            Thread th=new Thread(new Program().Test);            th.Start();            Console.ReadKey();        }        public void Test()   //執行個體方法        {            for (int i = 0; i < 1000; i++)            {                Console.WriteLine(i);            }        }    }}
除了運行執行個體方法,還可以線上程中運行靜態方法,代碼如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading; namespace AAAAA{    class Program    {        static void Main(string[] args)        {
 
            //Thread th=new Thread(new ThreadStart(Test));
            Thread th=new Thread(Test);            th.Start();            Console.ReadKey();        }        public static void Test()   //靜態方法        {            for (int i = 0; i < 1000; i++)            {                Console.WriteLine(i);            }        }    }}
2、帶一個參數的線程類

Thread類有一個帶參數的委託類型的重載形式。這個委託的定義如下:

[ComVisibleAttribute(false)]

public delegate void ParameterizedThreadStart(Object obj) 下面的代碼使用了這個帶參數的委託向線程傳遞一個字串參數:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading; namespace AAAAA{    class Program    {        static void Main(string[] args)        {           Thread th=new Thread(new ParameterizedThreadStart(Test));       
           //Thread th=new Thread(Test);
             th. Start( "這是個帶一個參數的Thread類。");             Console. ReadKey();        }         public  static  void  Test( Object  obj)        {             Console. WriteLine( obj);        }    }}

輸出結果:


3、帶多個參數的Thread類
由於Thread預設只提供了這兩種建構函式,如果需要傳遞多個參數,我們可以自己將參數作為類的屬性。定義類的對象時候執行個體化這個屬性,然後進行操作。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading; namespace AAAAA{    class Program    {        static void Main(string[] args)        {            Person p1=new Person();            p1._name="魏";            p1._age=24;            p1._sex='男';            //Thread th=new Thread(new ThreadStart(p1.ShowMsg));            Thread th=new Thread(p1.ShowMsg);            th.Start();            Console.ReadKey();        }    }    class Person    {        public string _name;        public int _age;        public char _sex;         public void ShowMsg()        {            Console.WriteLine("個人資訊:\n{0}\n{1}\n{2}", _name, _age, _sex);        }    }}
輸出結果:

五、前台和後台線程

使用Thread建立的線程預設情況下是前台線程,在進程中,只要有一個前台線程未退出,進程就不會終止。主線程就是一個前台線程。而後台線程不管線程是否結束,只要所有的前台線程都退出(包括正常退出和異常退出)後,進程就會自動終止。一般後台線程用於處理時間較短的任務,如在一個Web伺服器中可以利用後台線程來處理用戶端發過來的請求資訊。而前台線程一般用於處理需要長時間等待的任務,如在Web伺服器中的監聽用戶端請求的程式,或是定時對某些系統資源進行掃描的程式。

下面的代碼示範了前台和後台線程的區別:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading; namespace AAAAA{    class Program    {        static void Main(string[] args)        {            Thread thread = new Thread(Test);            thread.IsBackground = true;              thread.Start();        }        public static void Test()        {            Thread.Sleep(3000);        }     } }

如果運行上面的代碼,程式會等待3秒後退出,如果將注釋去掉,將thread設成後台線程,則程式會立即退出。

要注意的是,必須在調用Start方法之前設定線程的類型,否則一但線程運行,將無法改變其類型。

通過BeginXXX方法啟動並執行線程都是後台線程。確定

五、C# Thread類:判斷多個線程是否都結束的兩種方法

確定所有線程是否都完成了工作的方法有很多,如可以採用類似於對象計數器的方法,所謂對象計數器,就是一個對象被引用一次,這個計數器就加1,銷毀引用就減1,如果引用數為0,則垃圾搜集器就會對這些引用數為0的對象進行回收。

方法一:執行緒計數器

線程也可以採用計數器的方法,即為所有需要監視的線程設一個執行緒計數器,每開始一個線程,線上程的執行方法中為這個計數器加1,如果某個線程結束(線上程執行方法的最後為這個計數器減1),為這個計數器減1。然後再開始一個線程,按著一定的時間間隔來監視這個計數器,如是棕個計數器為0,說明所有的線程都結束了。當然,也可以不用這個監視線程,而在每一個背景工作執行緒的最後(在為計數器減1的代碼的後面)來監視這個計數器,也就是說,每一個背景工作執行緒在退出之前,還要負責檢測這個計數器。使用這種方法不要忘了同步這個計數器變數啊,否則會產生意想不到的後果。

方法二:使用Thread.join方法

join方法只有線上程結束時才繼續執行下面的語句。可以對每一個線程調用它的join方法,但要注意,這個調用要在另一個線程裡,而不要在主線程,否則程式會被阻塞的。

以上是本人在實際的學習中經過思考並總結出來的幾點膚淺想法。總之,我認為,要成為一名合格的程式員需要具備更多的條件,會思考、會學習、會動手是最基本的要求。在實際的工作當中,還要經常瞭解業界動態,活躍自己的思想,而不要閉門造車,封閉了自己的思想。經常性地加強學習,才能使得自身不會在這個變化太快的IT行業裡失去航向,才有資格成為一名合格的程式員,繼而向優秀的程式員邁進。希望這些知識可以協助更多的人。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.