2012-01-29 73 views
2

我正在寫一個Ruby程序,我有一個奇怪的問題。如何判斷方法或循環是否完成?

基本上這個想法是讓程序在後臺不斷運行。該程序每30秒檢查一次我的瀏覽器歷史記錄,並將任何新的歷史記錄項目上載到服務器。

# client.rb 
history = HistoryUploader.new(Chrome) 
# Run everything 
loop do 
    history.run 
    sleep 30 
end 

HistoryUploader類的重要組成部分,看起來像這樣

class HistoryUploader 
    def run 
    upload_history until local.last_seen_history_item == server.last_seen_history_item 
    end 

    def upload_history 
    # POST batches of history items to the server 
    end 
end 

我用這個代碼中看到的主要問題是,如果HistoryUploader.run時間超過30秒才能完成(這很可能也是因爲它發送多個http請求),client.rb的外部循環將嘗試再次調用run,並且我可能會收到併發請求到服務器,這真的會讓事情混淆。

有沒有辦法阻止run方法被調用兩次,直到它完成?

回答

2

我會使用一個接一個地執行請求的請求隊列。您還可以在HistoryUploader中放置一個簡單的布爾標誌,例如@is_uploading:

class HistoryUploader 

    attr_accessor :is_uploading 

    def initialize 
    @is_uploading = false 
    end 

    def run 
    if @is_uploading 
     return 
    end  
    upload_history until local.last_seen_history_item == server.last_seen_history_item 
    end 

    def upload_history 
    @is_uploading = true 
    # POST batches of history items to the server 
    # On uploading finished: 
    @is_uploading = false 
    end 
end 

如果你真的想,直到上傳完成後,你可以派遣一個線程並等待它完成使用擋主循環連接:

require 'thread' 

t = Thread.new do 
    #post to server 
end 
t.join 
3

我不認爲你有你認爲你有的問題。你描述你的代碼的方式仍然是單線程的。你沒有啓動一個新的線程來執行history.run,這意味着在你的history.run方法返回之前,睡眠30不會被執行。

是否需要使該線程取決於您要查找的行爲。如果您想在history.run完成後的30秒內觸發另一個對history.run的調用,您的代碼將立即執行此操作。如果您希望每隔30秒獨立運行history.run的執行時間(例如,history.run需要7.5秒,因此您希望在22.5秒內再次運行該查詢),那麼線程化解決方案可能是最多的優雅。

相關問題