2011-11-23 46 views
2

我有一個Winform,需要等待大約3-4個小時。我無法關閉並以某種方式重新打開該應用程序,因爲它在後臺執行某些操作,而它正在等待。Thread.Sleep()睡得更久

爲了實現等待 - 不會對UI線程和其他原因造成麻煩 - ,我有一個BackgroundWorker,我可以發送多少毫秒來等待並在其doWork事件中調用Thread.Sleep(waitTime);。在backGroundWorker_RunWorkerCompleted事件中,我會在等待後執行程序應該執行的操作。

這在開發機器上正常工作。即當等待結束時等待結束。但是在測試機器上,它會一直等待更長的時間。它發生兩次,第一次等待超過特定時間1小時,第二次等待大約2小時40分鐘。

難道這有什麼明顯的原因發生,或者我錯過了什麼?

的開發機是Win XP的試機是贏7

+1

爲什麼不使用Timer控件而不是後臺工作器中的thread.sleep? –

+1

同意..計時器應該這樣做 –

+1

爲什麼計時器的準確度比睡眠更好? AFAIK,定時器間隔由線程必須等待的Windows消息隊列上的定時等待實現,因此與sleep()相同。使用定時器會讓調用線程必須運行消息隊列 - 通常這是不可取的。嘗試在沒有使用sleep()的情況下等待一個通信棧內一小時的深度 - 需要痛苦且容易出錯的狀態機。 –

回答

2

看一看this article這解釋的原因:

Thread.sleep代碼(n)表示阻塞當前線程用於至少可Ñ 內發生的數目的時間片(或線程量程)的 毫秒。時間片的長度在Windows和不同處理器的不同 版本/類型上不同,通常 的範圍從15到30毫秒不等。這意味着該線程幾乎可以保證在012毫秒以上的時間內阻塞超過n個毫秒。您的線程會在n毫秒後重新喚醒的可能性大約爲 ,因爲這是不可能的。因此,Thread.Sleep對於 時間沒有意義。

通過它也解釋了爲什麼不使用的Thread.Sleep的方式;)

我同意其他建議使用定時器,而不是Thread.sleep代碼的。

+3

您的引用解釋了爲什麼使用Thread.Sleep進行準確計時並不是一個好主意,但在我看來,它並不能解釋爲什麼Thread.Sleep等待5個小時而不是4個小時。 –

+0

感謝您的鏈接.. – ViV

+1

@Werner Henze:我認爲它可以解釋它。由於Thread.Sleep根據您的機器使用了多個時間片,這些時間片都不是確切的,所以差異的總和可能會導致問題。當與機器上運行的其他線程共享時間片時,特別會導致超過一小時的差異。 – MatthiasG

2

在我的愚見,在等待時間上的差異不能僅僅被你給我們的信息解釋。我真的認爲,差異的原因在於開始睡眠的時刻。所以實際撥打Thread.sleep(waitTime);。你確定在你認爲這是睡覺的時刻?

而且,正如評論所建議的,如果你真的需要等待這麼久,考慮使用Timer來啓動所需的事件。甚至在您的應用程序中安排某種排序。當然,這取決於你的實際執行情況,因此說起來容易做起來難。但是'感覺'很傻,讓BackgroundWorker睡了這麼久。

+0

我確信睡眠在我認爲是的時候被調用。但看到有關Thread.Sleep()的答案和鏈接,我正在考慮使用Timer,以達到我的目的。 – ViV

3

我建議使用的ManualResetEvent來代替:

http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx

ManualResetEvent mre = new ManualResetEvent(false); 
mre.WaitOne(waitTime); 

... 
//your background worker process 
mre.Set(); 

作爲獎勵,你將不得不中斷這種睡眠更快的能力。

+0

謝謝!會給它一個鏡頭。 – ViV

+0

再次,工作在相同的機制睡眠()。同樣的問題。定時器是相同的 - 由操作系統在Windows Message Queue超時等待時啓動。所有這些定時器/睡眠/等待都使用相同的操作系統功能。 5個小時而不是4個小時只是..很奇怪。 –

0

PREFIX:這就需要。NET 4或更新

考慮讓你的異步功能和簡單地做:

await Task.Delay(waitTime); 

或者,如果你不能讓你的函數異步(或不願意),你也可以這樣做:

Task.Delay(waitTime).Wait(); 

這是一個單線解決方案,任何具有Reflector副本的人都可以驗證Task.Delay是否在內部使用計時器。