2011-12-19 54 views
3

我正在閱讀一些線程基礎知識,並在msdn網站上找到這段代碼。Thread.Sleep(1)的用途?

// Put the main thread to sleep for 1 millisecond to 
    // allow the worker thread to do some work: 
    Thread.Sleep(1); 

這裏是頁面的鏈接:http://msdn.microsoft.com/en-us/library/7a2f3ay4(v=vs.80).aspx

爲什麼主線程睡眠1毫秒?如果主線程連續運行,輔助線程是否不啓動其任務?或者,這個例子是否意味着需要1毫秒的任務?如果任務通常需要5秒才能完成主線程應該休眠5000毫秒?

如果這僅僅是關於CPU使用率,這裏是一個類似Question about Thread.Sleep

任何意見,將不勝感激。

謝謝。

+0

喬阿爾巴哈利寫關於就此問題,在這裏:http://www.albahari.com/threading/part2.aspx – dash 2011-12-19 23:33:49

+0

謝謝,這看起來像所有我需要的信息。 – YahooMania 2011-12-19 23:43:59

回答

7

在該代碼的1並不十分特別;它會總是結束睡眠時間比這更長,因爲事情並不那麼精確,放棄你的時間片不等於操作系統的任何保證,當你將它恢復。

Thread.Sleep()中時間參數的用途是,您的線程將產生至少至少大致的時間量。

這樣的代碼只是明確地放棄它的時間。一般來說,這樣的代碼不應該被需要,因爲操作系統會爲你管理你的線程,搶先中斷它們去處理其他線程。

這種代碼往往是在「線程的例子」,其中筆者要迫使一些人爲的發生,證明一些競爭條件,等等(這似乎是在你的例子)


使用

正如Jon Hanna對同一問題的回答所指出的那樣,Sleep(0)Sleep(1)(或任何其他非零數字)之間存在細微但重要的區別,並且正如ChrisF所暗示的,在某些線程情況下,這可能很重要。

這兩個都涉及線程優先級;線程可以被賦予更高/更低的優先級,這樣只要有更高優先級的線程有任何工作需要執行,較低優先級的線程就會執行從不執行。在這種情況下,可能需要Sleep(1) ... 但是 ...

低優先級線程也受制於其他進程在同一個系統上執行的操作;所以雖然你的進程可能沒有更高優先級的線程正在運行,但如果有其他線程正在運行,你的程序仍然不會運行。

這不是通常你需要擔心,雖然東西;默認優先級是'正常'優先級,在大多數情況下,您不應該改變它。提高或降低它有很多的影響。

+0

所以這一點代碼實際上是擊敗線程的目的?目的是一次執行多個任務,而無需等待對方完成。最好不要使用它? – YahooMania 2011-12-19 23:41:38

+0

@YahooMania不,在某些情況下這樣做至關重要。 – 2011-12-19 23:56:16

+0

@YahooMania但你不一定都會遇到這種情況,除了線程示例之外。這段代碼的存在有助於說明一個觀點。 – 2011-12-20 00:01:48

0

這只是他們想要確保工作線程必須打印的機率例 - 着想「的工作線程:工作......」至少一次主線程殺死它。

正如Andrew所暗示的那樣,這在該示例中非常重要,尤其是因爲如果您在單處理器計算機上運行,​​主線程可能不會放棄處理器,在它有機會迭代一次之前殺死後臺線程。

2

如果主線程根本不睡覺,那麼其他線程根本無法運行。

插入Sleep的任何長度允許其他線程一些處理時間。使用較小的值(在這種情況下爲1毫秒)意味着主線程不會鎖定。您可以使用Sleep(0),但是Jon Hanna指出,它與Sleep(1)(或實際上任何正值)具有不同的含義,因爲它只允許同等優先級的線程運行。

如果任務需要5秒鐘,那麼主線程將總共休眠5,000毫秒,但分佈時間更長。

+0

不完全正確。最小值爲0,但在這種情況下不會產生低優先級的線程。 – 2011-12-19 23:57:41

4

Thread.Sleep(0)將放棄線程的時間片的其餘部分,如果相同優先級的線程準備好安排。

Thread.Sleep(1)(或任何其他值,但1是具有此效果的最低值)將無條件放棄線程的其餘部分。如果它想要確保即使較低優先級的線程有機會運行(並且這樣的線程可以做某些阻止該線程的東西,它必須),那麼這是一個需要解決的問題。

http://www.bluebytesoftware.com/blog/PermaLink,guid,1c013d42-c983-4102-9233-ca54b8f3d1a1.aspx有更多。

0

我今天注意到有趣的事情。中斷一個線程拋出一個ThreadInterruptedException。我試圖抓住例外,但由於某種原因不能。我的同事建議我在捕獲聲明之前放置Thread.Sleep(1),並允許我抓住ThreadInterruptedException

 // Start the listener 
     tcpListener_ = new TcpListener(ipAddress[0], int.Parse(portNumber_)); 
     tcpListener_.Start(); 
     try 
     { 
      // Wait for client connection 
      while (true) 
      { 
       // Wait for the new connection from the client 
       if (tcpListener_.Pending()) 
       { 
        socket_ = tcpListener_.AcceptSocket(); 
        changeState(InstrumentState.Connected); 

        readSocket(); 
       } 
       Thread.Sleep(1); 
      } 
     } 

     catch (ThreadInterruptedException) { } 

     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message, "Contineo", MessageBoxButtons.OK, MessageBoxIcon.Error); 
      Console.WriteLine(ex.StackTrace); 
     } 

一些其他類...

 if (instrumentThread_ != null) 
     { 
      instrumentThread_.Interrupt(); 
      instrumentThread_ = null; 
     } 
+0

如果您在'Start'之前取出'Pending()'測試並放棄AcceptSocket()'塊,它也可能被捕獲。原因是我的答案的延伸。線程將不會有'ThreadInterruptedException'拋出它,直到它阻塞或放棄它的時間片(不只是到它的量子的末尾,並返回等待下一個量子)爲止。Thread.Sleep(1) '原因,但'Thread.Sleep(0)'不。進入監視器或等待事件也會給它一個被拋出的機會。 – 2011-12-20 23:30:30