簡體   English   中英

BackgroundWorker和Timer,一次處理一個項目

[英]BackgroundWorker and Timer, handling one item at a time

我的應用程序監視用戶可以在其中上傳文件的目錄。 當檢測到新文件時,它將被添加到隊列中。 我有一個計時器,它在隊列中運行,並確定文件是否已完成上傳。 如果有任何完整的文件,它將使用最新文件並開始運行后台任務(使用BackgroundWorker)。

我的問題是我不知道在后台任務運行時如何處理計時器。 例如,如果計時器設置為10秒並且后台工作程序仍在工作,則我希望計時器跳過另一個后台工作程序的執行,直到下一次迭代為止。

另外,每個任務的信息都存儲在Queue(一個ListView控件)中,並將ListViewItem傳遞給后台工作人員。 我很好奇,如果傳遞ListViewItem有任何副作用。

謝謝!

您可以將准備處理的文件存儲在另一個隊列中(例如Queue <string>),然后讓BgWorker連續輪詢該隊列。 您也可能會獲得更好的性能,更少的空閑時間。 您將必須保護隊列(使用Monitor),並讓BgWorker使用Monitor.Wait,當隊列為空時。

要想出個主意,請尋找馬克·格雷夫(Marc Gravell)對這個問題的答案。

在沒有看到您正在談論的代碼的情況下,真的很難回答。 但是,如果必須同步多個異步事件(檢測到文件已下載,將文件添加到隊列,處理隊列),則建議創建一個可以完成所有任務的單個BackgroundWorker。 這樣,您的工作人員就可以輕松地測試每個步驟的狀態。 我會避免創建多個線程並嘗試使其同步,這是非常非常有問題的。

我也不會在UI數據結構(如ListView控件)中存儲任何后台任務信息。 在BackgroundWorker中創建一個回調或事件,該回調或事件將在需要顯示某些內容時提醒UI。

您正在尋找BackgroundWorker.IsBusy屬性嗎?

您可以做的最簡單的事情是在BackgroundWorker中進行所有工作(包括檢查文件夾):檢查是否有事要做,如果可以,請這樣做,否則請使用Sleep(time)或WaitOne(time)掛起線程一段時間。

我認為這里不需要線程安全隊列,因為無論如何文件夾都是異步更新的。 因此,您只需要一個線程, 但是需要一種方法來停止它。 這就是為什么AutoResetEvent.WaitOne(time)優於Sleep(time)的原因-您可以從主線程發出事件信號,以盡早結束后台工作人員。

在您的Timer.Tick處理程序上,檢查BackgroundWorker.IsBusy屬性以確定它是否准備好進行其他工作。 如果沒有,請跳過工作,直到下一個Tick。

您可以創建一個線程隊列,在其中放置工作。 您的后台工作人員會從隊列中取出項目並執行工作。 需要考慮一些事情:

  • 隊列必須是線程安全的,如果隊列為空,您很可能希望后台工作人員阻止該隊列,並在某個項目可用時喚醒它。 我確定somone已經做出了如此出色的排隊。
  • 您發布到隊列中的項目將在另一個線程(backgroundworker)中進行操作。 確保以線程安全的方式完成此操作(例如,不要將項目發布到主應用程序和后台工作程序都會更改的隊列中)

另一種簡便的方法是

  • 對應用程序中的項目進行排隊。 第一次啟動背景工作人員。
  • 當您收到后台工作人員完成的事件時,請從隊列中選擇下一個項目,然后使用該項目再次啟動后台工作人員。
  • 您仍然需要關心線程安全性。 將項目發送給后台工作人員后,請確保僅后台工作人員對其進行操作(例如,如果您只是向其發送字符串,請向其發送該字符串的副本)

我沒有在定時器上跟着你。 如果后台工作人員完成了操作,那么您應該獲得一個事件,並且您將知道它已完成,而無需計時器進行檢查。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM