詳細介紹C#Thread點點滴滴

來源:互聯網
上載者:User
用C#的Thread做了一個簡單計時器。為了讓自己45分鐘後就可以休息一次,45分鐘過後會響音樂提示。

開始使用的TimeSpan相減的方式,在Thread的啟動函數中也就是這樣寫的:

  1. public void CountTime(){               while (true)   {      TimeSpan tsNew = new TimeSpan(DateTime.Now.Ticks);      TimeSpan tsIn = tsNew - tsOld;      if (tsIn.Minutes >= 1)      {             while (true)         {             TimeSpan tsNewer = new TimeSpan(DateTime.Now.Ticks);             TimeSpan tsIner = tsNewer - tsNew;             if (tsIner.Minutes >= 10)             {                //十分鐘後線程重啟                 tsOld = tsNew;                 break;             }         }                }   }}

後來發現這種方法效率太低了。當然,可以使用Thread.Sleep(20);這個函數降低CPU佔用時間。其實中間加入Thread.Sleep(20);就可明顯的降低CPU消耗。後來發現C#中的Thread中內建有函數join(),這個函數可以使線程等待一段時間。調用方法如下

th.Join(new TimeSpan(hours, minutes, seconds));在等待的這段時間裡線程處於WaitSleepJoin狀態。

當然也可以調用Thread.Sleep(millionseconds);這裡提一下Sleep和Join的區別

當線程執行Sleep時系統就退出執行隊列一段時間,當睡眠結束時,系統會產生一個時鐘中斷,從而使線程回到執行隊列中恢複線程的執行。Sleep方法如果參數是0,代表這個線程應當掛起讓其他等待的線程運行,這裡cpu回重新分配控制權,也有可能是剛才的執行的程式。這樣就會有cpu佔用總是100%的情況發生。有時你介面死了,但是你還是可以移動滑鼠。如果是Timeout.Infinite,就代表將使線程休眠,直到它被調用 Thread.Interrupt 的另一個線程中斷或被 Thread.Abort 中止為止。
如果父線程先於子線程結束,那麼子線程將在父線程結束的同時被迫結束。Thread.Join()方法使父線程等待,直到子線程結束。Join方法有傳回值,當值為true,代表線程終止。false的話代表線程在等待了那段時間後還未終止。如果線上程Unstarted狀態時,調用join()就會有ThreadStateException異常。如果線程已經終止,那麼調用這個函數,會立即得到傳回值。

例如下面的主程式

...ThreadStart st = New ThreadStart(fun);Thread th = new Thread(ThreadStart st);th.Start();Application.Exit();... //下面是fun函數void fun(){    while(true)    {            ...    }}

這段程式的唯一毛病就是有可能在主程式退出後,從線程還沒有結束。(這個從線程真可憐...)

這裡順便再提一下線程的幾個狀態:

  建立:當建立一個新進程時,也為該進程建立了一個線程。線程還可以建立新線程。

  就緒:線程已獲得除處理機外的所有資源。

  運行:線程正在處理機上執行。

  阻塞:線程因等待某事件而暫停運行。

  終止:一個線程已完成。

但是C#的線程中多了幾個狀態:

Aborted,AbortRequested,Background,Running,Stopped,StopRequested,Suspended,SuspendRequested,Unstarted,WaitSleepJoin。

Abort()將導致ThreadState.AbortRequested調用Abort()的線程獲得控制權之後導致ThreadState.Aborted,AbortRequested與Aborted的區別在於一個停止一個未停止。而Stopped則是線程終止。但是我反覆實驗多次發現當調用Abort()函數後,線程狀態會變為Stopped。如何變為Aborted狀態,還在研究中。其他幾個狀態差不多。都是調用相應的函數會產生相應的狀態請求,還有過一段時間才能到底相應的狀態。至於Unstarted是還未調用Start()函數,Running是調用Start()或者Resume()函數的結果。WaitSleepJoin是在等待I/O,或者是調用Join()方法。這裡Join()和Sleep()方法的不同還在於調用Join()線程狀態進入WaitSleepJoin,調用Sleep()線程狀態還是Running。

掛起線程的方法是Suspend();調用這個方法後,線程處於SuspendRequest狀態。Suspended()調用後如果線程仍然在執行join()方法,因為Suspended()要讓線程到達安全點之後它才可以將該線程掛起,此時那線程狀態就是SuspendRequested|WaitSleepJoin。但是這裡的join裡的時鐘依然在計數。所以現在還不知道用什麼方法來暫停這個join計數,當然也可以不使用join解決徹底暫停線程這個問題。現在不明白哪個Suspended()函數是幹什麼的,因為線程依舊在運行中。另外值得一提的是現在不提倡使用Suspend()和讓線程調用Suspend()後再次恢複的Resume()方法。原因很簡單,因為這兩個方法是由另外的線程執行,另外的線程並不能準確的知道被Suspend()的線程處於何種狀態,如某個類的建構函式執行時期,或者析構等。所以用這個函數來同步很危險。

另外,要注意的是Thread.Sleep(n)這個n不能精確的控制時間。如果你認為要線程要隔多長時間,這個控制就有問題。如果當前的線程是一個前台線程,那麼Thread.Sleep(n)就要在大於n的時間才能退出。如果是後台進程,當主程式退出後,這線程就再也不能喚醒..悲慘..所以一般也建議不用Thread.Sleep()函數。另外Sleep函數也不能用於同步.peter說程式的Sleep函數代表了一個很爛的設計。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.