2010-06-16 72 views
0

我有一個使用BackgroundWorker執行一系列測試的表單。我使用ProgressChanged事件將消息發送到主線程,然後主線程完成所有更新。我已經梳理了我的代碼,以確保我沒有對後臺工作人員的UI做任何事情。我的代碼中沒有while循環,BackgroundWorker的執行時間有限(以秒或分鐘爲單位)。但是,由於某些原因,當我鎖定我的計算機時,往往會在登錄時掛起應用程序。事情是,BackgroundWorker在發生這種情況時甚至沒有運行。我認爲它與BackgroundWorker相關的原因是因爲只有在加載應用程序後才執行BackgroundWorker(僅在給定特定用戶輸入時才運行),表單纔會掛起。BackgroundWorker可能導致我的應用程序掛起

我通過RunWorkerAsync方法從我的用戶界面中的TreeView中傳遞一個TreeNodes列表,但我只讀取工作線程中的那些節點。我對它們做出的任何修改都是在UI線程中通過progressChanged事件。

我使用了Thread.Sleep在我的工作線程在一定的時間間隔執行測試(涉及超過一個TCP套接字,這是不是在工作線程創建發送消息)。

我,爲什麼我的應用程序可能掛完全不知所措。我確信我在某個地方做了「非法」的事情,我只是不知道該怎麼做。

+1

要縮小問題,註釋掉ProgressChanged處理程序,看看它是否仍然鎖定。如果它仍然鎖定,則保留註釋部分,直到它工作。 – AMissico 2010-06-16 17:24:41

+0

*技術上*,你不應該從BGW中的UI對象中讀取。我建議使用LINQ向BGW線程傳遞'IEnumerable '(或任何您需要的數據,如果不是'string')。 – 2010-06-16 17:35:15

+0

問題是鎖定不容易重現。有時它可能會在幾個小時內不會發生,所以可能需要幾天時間才能縮小這個範圍。使用LINQ而不是RunWorkerAsync的參數將TreeNodes列表傳遞給我的線程有什麼好處? – alexD 2010-06-16 19:39:30

回答

0

那麼,這個人是舊的,但事實證明,問題是完全無關的我的代碼。由於我們軟件的最近更改,日誌記錄的數量呈指數級增長,並且我們的日誌緩衝區溢出導致應用程序崩潰。這只是巧合,這發生在我正在編寫這段特定代碼的同時。無論如何,我仍然確信我沒有對BackgroundWorker的UI元素進行任何操作,即使它與檢查/取消選中TreeNode一樣微不足道。

1

我通過RunWorkerAsync方法從我的UI中的TreeView傳遞此線程列表TreeNodes,但我只讀取工作線程中的這些節點。

通過「只讀」我假設你的意思是「只有訪問屬性獲得者」。但是屬性獲取器可以執行不受控制的代碼 - 例如,TreeNode.IsSelected將調用本地方法併發送Windows消息(使用Reflector查看)。

相反,你應該提取你在UI線程TreeView中所需要的數據,並將其傳遞給後臺工作。你不僅可以避免這個問題,而且你的設計會更加鬆散。

+0

我已經擴展了TreeNode類來將一堆數據添加到我需要使用的節點中。將這些數據提取到數據結構並傳遞給它們將是很多工作。如果我只是將TreeNodes傳遞給BGW,然後在BGW中創建每個節點的副本,然後再訪問它們的任何數據? – alexD 2010-06-16 18:14:15

+0

我會說咬一口。從後臺工作人員訪問UI元素會導致未定義的行爲。即使你以某種方式得到它的工作,這將是一個維護的噩夢。 – Joe 2010-06-16 19:22:51

+0

如果我只訪問我自己的類的屬性,我知道沒有任何特殊的調用正在進行,該怎麼辦?如果我需要「IsChecked」屬性,我可以創建自己的屬性並在將它交給BGW之前進行設置。 – alexD 2010-06-16 19:37:35

0

聽起來像,其中的UI組件已經在後臺線程創建沒有消息泵可怕UserPreferenceChanged事件問題。主UI線程將事件同步發送到所有已註冊的UI窗口,並且會掛起,因爲後臺工作線程上的UI組件無法處理事件。

相關問題