2012-12-14 233 views
1

我從How to wait for a BackgroundWorker to cancel?閱讀的答案,但我無法找到一個解決我的具體的問題:如何等待BackgroundWorker完成?

我的應用程序加載大量的數據,但在大多數情況下,這些數據不會被立即要求應用程序啓動後。

爲了最大限度地減少用戶實際請求數據時的延遲,我使用BackgroundWorker加載它,該應用程序在應用程序啓動時啓動。希望當用戶請求數據時,BackgroundWorker已經完成。

然而,在某些情況下,它可能沒有。在這些情況下,我想在向用戶顯示任何內容之前等待加載完成。我可以想到的所有技術都有競爭條件:例如,如果我設置了AutoResetEvent,當用戶請求數據時,我不能使用WaitOne(),因爲AutoResetEvent可能已經發出信號;如果我添加一個布爾值loading_complete標誌並在調用WaitOne之前檢查它,loading_complete可能會在ckecing之後設置爲true,但在WaitOne調用之前將永遠不會返回...

任何想法?

編輯:感謝解決方案的@ 500-InternalServerError;使用ManualResetEvent的作品很棒。感謝其他人的建議。

+0

如果使用.net 4.0或更高版本,可以使用'Task'。 –

+0

@HamletHakobyan不幸的是,我在Windows Phone上SilverLight,它沒有'Task' ... –

+1

好吧,只需在RunWorkerCompleted事件中啓用一個按鈕即可。 –

回答

0

你把一次的BackgroundWorker在WorkCompleted事件處理

+0

當BackgroundWorker完成時,至少沒有發生任何事情,我知道當我啓動BackgroundWorker時:我只使用它在 –

+0

之後加載的數據我認爲Baboon意味着BackgroundWorker應該觸發該事件,並且所有其他線程都應該等待在這個事件之前恢復他們的工作。 – didierc

+0

@didierc:據我所知,但當我輸入需要數據完全加載的應用程序部分時,我無法知道事件是否已經觸發。換句話說,當我到了需要等待數據的地步時,WorkCompleted事件可能會或可能沒有開始,如果我使用布爾標誌來檢查我會遇到競爭條件。 –

0

用一個簡單的互斥鎖BackgroundWorker鎖定做什麼應該發生,並有其他線程等待完成獲取和釋放它。一旦完成BackgroundWorker,讓它釋放該鎖,並且所有其他線程應該能夠繼續其工作。

可能有一些特定的C#方式做到這一點(我認爲Monitor class可能會得心應手)。

更新:實際上,解決問題所需的對象是一種形式的條件變量,作爲鎖存器工作,並且,如OP所述,ManualResetEvent涵蓋了該特定需求。

-1

使用布爾標誌,在後臺worker完成的事件處理程序中將其設置爲true。

當您需要檢查數據是否加載時,只需檢查變量。

確保在嘗試訪問它之前先將其鎖定,以避免競爭狀況。

如果數據在請求時沒有準備好,那麼可以在該點添加另一個事件處理程序給後臺工作人員已完成的事件,該事件需要完成數據處理。

0

後臺工作者支持RunWorkerCompleted事件。該事件可用於確定加載是否已完成。

有兩個條件

  • 用戶請求數據工人完成後。

爲了減少事情的複雜性,您可以添加一個布爾成員變量,當後臺工作人員開始加載數據時,該變量將被設置爲false。一旦數據加載完成,runworkercompleted事件將觸發它將變量設置爲true,這將幫助您確定數據是否加載。

  • 用戶在worker完成之前(可以根據上述bool變量確定)請求數據並等待數據加載。

當用戶請求的數據,則可以設置一個標誌/另一個bool變量如

WaitingForData = TRUE;

當RunWorkerCompleted事件被觸發時,它將檢查WaitingForData的狀態,如果它爲true,它將顯示數據。這樣,你不需要等待線程完成。

使用此方法將幫助您避免任何競態條件或線程間通信。

+0

這聽起來像個好主意,但它並沒有說明我的應用程序中有多個數據可視化頁面,並且BackgroundWorker不知道將數據發送到哪個數據... @ 500-InternalServerError的解決方案工作正常好,但是。 –

+0

如果您有多個組件顯示數據,則可以在多個位置使用該事件。 –

+0

考慮到UI佈局的成本,使用數據呈現所有UI元素是不可行的,因爲最後只會顯示一個。 –