2011-04-30 101 views
0

如何以不完全低效的方式實現繁忙等待?我面臨的問題是我只能以拉的方式加載我的模型的數據,這意味着我必須以連續的方式調用getXYZ()方法。在C中忙於等待#

對於用戶交互,這必須發生得不夠快,但足夠快,當GUI中的狀態發生變化時,模型可以被注意到,並且getXYZ()方法接收到新狀態。

我的做法僅僅是:

while (c.hasChanged()) { 
    Thread.sleep(500); 
} 
updateData(); 

有沒有更好的機制?

+2

看看後臺線程(BackgroundWorker的或裸線程) – Flawless 2011-04-30 06:34:21

+0

請說明什麼樣的應用是輪詢模式在這裏。 – 2011-04-30 08:25:49

回答

5

你的問題似乎可以用Threading解決。

在WPF中,你可以這樣做:

Thread t = new Thread((ThreadStart)delegate() { 
    while (true) { 
     Thread.sleep(500); 
     if (c.hasChanged()) 
      Dispatcher.Invoke((Action)delegate() {updateData();}); 
    } 

}).Start(); 

在的WinForms

Thread t = new Thread((ThreadStart)delegate() { 
    while (true) { 
     Thread.sleep(500); 
     // this must derive from Control 
     if (c.hasChanged()) 
      this.Invoke((Action)delegate() {updateData();}); 
    } 

}).Start(); 

有可能會丟失參數Invoke(這是需要執行調用UI線程上的代碼),但我m寫這從我的大腦,所以沒有intellisense處置:D

在.NET 4中,您可以使用TaskFactory.StartNew,而不是自己產生一個線程。 在.net < = 4中,您可以使用線程的TreadPool。 但是我記得你需要立即執行這個操作,因爲你希望它儘快在線檢查,線程池不會向你保證(它可能已經滿了,但不是很可能:-)。 只是不要做一些愚蠢的事情,比如在一個循環中產生更多的東西!

和線程裏面你應該把像

while (!Closing) 

檢查,使線即可完成,當你需要它沒有退出時把截止到真實而不必訴諸壞事像t.Abort(); 的執行t.Join()關閉檢查程序線程。

編輯:

我忘了說,閉幕式應該是一個布爾屬性或VOLATILE布爾值,而不是一個簡單的布爾,因爲你不會保證線程所能完成(以及它會在如果您正在關閉應用程序,但最好按照您的意願完成)。 volatile關鍵字旨在防止(僞)編譯器對假定變量值無法更改的代碼應用任何優化

+0

就我的理解而言,除了最瑣碎的程序以外,永遠不應該使用VOLATILE。這不僅對AMD和安騰處理器都不安全。約瑟夫阿爾巴哈利也得到了英特爾處理器的簡單測試代碼,表明揮發是這裏不安全或者 - http://www.albahari.com/threading/part4.aspx#_The_volatile_keyword – Johnv2020 2011-05-02 16:11:25

+0

@約翰我同意你的看法,但由於這種特殊的揮發性布爾將在一個循環中讀取它不是是否會被讀取真的那麼重要錯誤一次或兩次(如果這是並不重要,因爲高速緩存一致性或什麼的,在某些時候它會重新讀取)。如果編譯器用while(true)替換while(bClos​​ing)會出現什麼問題。我不是框架專家,但文檔摘錄說編譯器永遠不會對volatile變量進行優化。無論如何,最好的辦法是使這個財產。 – 2011-05-14 19:08:51

2

從你的帖子中不清楚你正在嘗試做什麼,但它聽起來像你應該把你的模型/服務調用放在一個單獨的線程(通過後臺工作者或異步委託),並使用模型/服務調用在完成時通知UI。然後,您的UI線程可以執行繁忙的工作,例如顯示進度條,但不會變得無法響應。

2

如果您要從GUI進行輪詢,請使用(WinForms)Timer。

如果這是某種背景過程,您的睡眠()可能是較小的邪惡。

0

明確忙等待是邪惡的,必須儘量避免。

如果無法避開它,然後使用觀察者設計模式構建應用程序並註冊感興趣的對象到執行輪詢,由一個線程支持的對象。

這樣,你有一個乾淨的設計,圍醜陋的東西,在一個地方。