2017-04-06 75 views
8

我們有一個我們正在支持的舊項目,並且最有可能由於多線程而發生的問題。 原執行者在執行問題部分之前通過執行Thread.sleep'固定'它。 解決方法可行,但由於該部分位於循環內,因此thread.sleep會在該部分完成所需的時間內添加多個分鐘。有沒有辦法強制應用程序作爲單線程運行?

在過去的一個月中,我們一直在嘗試用較低的睡眠值,但我們希望找到根本原因。在我們的調查中,我們對私人物品做了lock,只要我們覺得這樣會有所幫助。 我們尋找任何可能產生額外線程的東西 - 無法找到。 沒有Thread.start並且沒有ThreadPool用法。 令我們困惑的是,在調試過程中,我們發現我們的主線程在大約8個其他線程中,我們不知道是誰產生了它們。 這些是後臺線程,所以首先想到的是線程池,但正如我提到的代碼中沒有提到它。

它是.net 2.0所以沒有Async s。 這只是大型應用程序的一部分,所以它是一個Windows服務,但我們將其作爲CMD運行,以便能夠輕鬆進行調試主應用程序本身是一個Windows窗體桌面應用程序。 它也使用COM +組件,如果有任何幫助。

我試過[STA]而不是[MTA]。 也如上所述鎖定。 MemoryBarrier也是如此。

我們仍然遇到問題。

該問題基本上是損壞的數據集和對象的空值,他們不應該。 它發生在每25-100次迭代大約一次,因此再生不是直接進行的,但我們專門爲此問題設計了一個測試來嘗試再現它。

所有這些都將我們引向線程問題的方向。

回到最初的問題 - 誰可能通過產生這些額外的線程,我們如何防止這些線程被創建?

enter image description here

請注意標有紅色的線 - 這些都是後臺線程而據我們可以看到沒有提到他們的代碼。

截圖中的可疑線程正在主動修改dataset中的列。問題是 - 調用線程執行的SetColValueOnRow函數的方法是典型的,並且不使用任何類型的線程。

此應用程序的CPU關聯設置爲1個核心[原工作周圍的部分]

感謝

編輯:數據庫是Oracle 12c的,但寫之前,我們面對發生的問題數據庫。 他們通常在數據集,其中整個記錄或它的一些列的可擦一次每隔幾個測試迭代

+0

什麼類型的應用程序(winforms,service,...) – pm100

+0

這只是更大的應用程序的一部分,所以它是一個Windows服務,但我們將其作爲CMD運行,以便能夠輕鬆進行調試 主應用程序本身是一個Windows窗體桌面應用程序。 – AngelicCore

+0

當再現/調試這個問題時,我們只運行這個部分,我們不運行應用程序的其餘部分。 – AngelicCore

回答

2

我認爲你需要調查原因的Thread.sleep工作發生。這聽起來不像代碼本身產生額外的線程,但你必須通過整個代碼庫才能找到它 - 包括COM +組件。

所以我要做的第一件事就是在調試中啓動程序,只需按F10鍵即可進入程序。然後打開線程調試窗口,看看你是否看到與你的問題中給出的相同數量的線程。如果你這樣做,那麼這些只是線程池中的線程,你的問題可能與多線程無關。

如果看不到相同數量的線程,則嘗試在程序的各個階段設置斷點,並查看是否可以找到在哪些線程創建的位置。當你找到他們創建的地方時,你可以嘗試在那個地方添加一些鎖定。但是,您的問題仍然可能不是由多個線程損壞內存引起的。您應該調查,直到您確信問題是由於多個線程或其他問題。

我懷疑問題可能與一個或多個COM +組件有關,也可能是代碼正在調用一些長時間運行的數據庫存儲過程。無論如何,我懷疑Thread.sleep的工作原因是因爲在開始下一個操作之前,它給了可疑組件足夠的時間來完成它的操作。

如果這個理論是正確的,那麼它表明在操作和Thread.Sleep被賦予足夠大的值以允許操作完成時存在一些交互 - 沒有交互問題。這也表明,也許其中一個COM +組件正在異步地做一些事情。解決方案可能是使用COM +組件代碼中的鎖或關鍵部分。另一個想法是重新設計導致問題的代碼段,以允許同時進行多個操作。

因此,您遇到的問題可能不是由於您正在查看的C#代碼中存在多個線程 - 可能是由於長時間運行的操作,如果在啓動之前沒有足夠的時間來完成,有時會失敗下一個操作。這可能是也可能不是由於C#代碼中的多個線程。

+0

你是對的 - 這是我想要做的事情之一。該應用程序是巨大的,並不簡明,所以顯然這將需要很長的時間。 – AngelicCore

相關問題