首頁 >後端開發 >C#.Net教程 >詳細介紹C#Thread點點滴滴

詳細介紹C#Thread點點滴滴

黄舟
黄舟原創
2017-03-20 13:17:171893瀏覽

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函數代表了一個很爛的設計。

 

以上是詳細介紹C#Thread點點滴滴的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn