2012-02-21 177 views
8

在性能監視器中監視我的.NET應用程序我可以看到.NET CLR LocksAndThreads /#當前邏輯線程隨着時間穩定增加(當前爲293),表示線程堆棧正在泄漏。當前邏輯線程增加/線程堆棧正在泄漏

我可以找到很多文章告訴我這是問題,但沒有告訴我如何找到原因 - 我從哪裏開始?溫博格能告訴我問題在哪裏?

這是我在3小時性能監控告訴我現在的邏輯線程是150:

thread leak

這是線程窗口的輸出,它並沒有告訴我,因爲我不能訪問他們的調用堆棧 - 它們大多被標記爲[不可用]或[在睡眠中,等待或加入] | [外部代碼]:

Unflagged  141024 124 Worker Thread <No Name>  Normal 
Unflagged > 0 0 Unknown Thread [Thread Destroyed]  
Unflagged  136272 2 Worker Thread <No Name>  Highest 
Unflagged  133060 7 Worker Thread vshost.RunParkingWindow [Managed to Native Transition] Normal 
Unflagged  136952 10 Main Thread Main Thread [edited].Program.Main Normal 
Unflagged  134544 9 Worker Thread .NET SystemEvents [Managed to Native Transition] Normal 
Unflagged  136556 11 Worker Thread Worker Thread [edited].MessageService.ProcessJobs.AnonymousMethod__0 Normal 
Unflagged  141364 113 Worker Thread <No Name> [In a sleep, wait, or join] Normal 
Unflagged  140896 0 Worker Thread [Thread Destroyed]  Normal 
Unflagged  136776 19 Worker Thread <No Name> [In a sleep, wait, or join] Normal 
Unflagged  135704 20 Worker Thread <No Name> [In a sleep, wait, or join] Normal 
Unflagged  136712 21 Worker Thread <No Name> [In a sleep, wait, or join] Normal 
Unflagged  134984 22 Worker Thread <No Name> [In a sleep, wait, or join] Normal 
Unflagged  134660 23 Worker Thread Worker Thread [edited].BroadcastService.ProcessJobs.AnonymousMethod__1d Normal 
Unflagged  140224 152 Worker Thread <No Name>  Normal 
Unflagged  140792 157 Worker Thread <No Name>  Normal 
Unflagged  137116 0 Worker Thread <No Name>  Normal 
Unflagged  140776 111 Worker Thread <No Name>  Normal 
Unflagged  140784 0 Worker Thread [Thread Destroyed]  Normal 
Unflagged  140068 145 Worker Thread <No Name>  Normal 
Unflagged  139000 150 Worker Thread <No Name>  Normal 
Unflagged  140828 52 Worker Thread <No Name>  Normal 
Unflagged  137752 146 Worker Thread <No Name>  Normal 
Unflagged  140868 151 Worker Thread <No Name>  Normal 
Unflagged  141324 139 Worker Thread <No Name>  Normal 
Unflagged  140168 154 Worker Thread <No Name>  Normal 
Unflagged  141848 0 Worker Thread [Thread Destroyed]  Normal 
Unflagged  135544 153 Worker Thread <No Name>  Normal 
Unflagged  142260 140 Worker Thread <No Name>  Normal 
Unflagged  141528 142 Worker Thread <No Name> [In a sleep, wait, or join] Normal 
Unflagged  141344 0 Worker Thread [Thread Destroyed]  Normal 
Unflagged  140096 136 Worker Thread <No Name>  Normal 
Unflagged  141712 134 Worker Thread <No Name>  Normal 
Unflagged  141688 147 Worker Thread <No Name>  Normal 

更新: 我,因爲跟蹤的罪魁禍首降到System.Timers.Timer。即使此計時器在每個Elapsed事件中調用了空方法,它仍會無限期地提高邏輯線程數。只需將計時器更改爲DispatcherTimer即可解決問題。

我開始在應用程序中運行!dumpheap -type TimerCallback時看到大量數據,正如this question中提到的那樣,查看了我應用程序中的所有計時器。

我仍然想知道如何通過Windbg調試檢測到這種情況,而不是通過禁用定時器/檢查性能/重複方法導致我進行修復。即任何可能告訴我哪個定時器正在產生問題的東西。

+0

你知道什麼是創造它們,爲什麼? – 2012-02-21 12:44:02

+0

我的應用程序有很多移動部件,所以「爲什麼」將是許多不同的後臺任務。我試圖找出增加的來源,找出「什麼」。 – DaveO 2012-02-22 09:11:36

回答

4

這通常是由於線程池線程卡住而未完成引起的。每隔半秒,線程池管理器允許另一個線程開始嘗試處理積壓。這一直持續下去,直到達到ThreadPool.SetMaxThreads()所設置的最大線程數。默認情況下,4核機器上的數字爲1000。

使用Debug + Windows + Threads查看正在運行的線程。他們的調用堆棧應該明確爲什麼它們被阻塞。

+0

嗨漢斯。我看了一下,但如上面更新,我無法真正看到任何有用的信息。是否有可能是由非託管代碼造成的,這就是爲什麼大多數列出的線程都不可用? – DaveO 2012-02-22 09:09:45

+0

顯然我最大。 ThreadPool.GetMaxThreads的線程爲1023,但perfmon當前顯示的是超過2400個當前邏輯線程。 – DaveO 2012-02-29 02:21:34

+0

嗯,它總是250的倍數,除非明確覆蓋。幾乎沒有問題的是,2400線程當然會超過開心點和真正的問題。擁有1023並不會讓它變得更好。 – 2012-02-29 02:29:04

1

嘗試所有長時間運行的操作(100+ ms數據庫調用,磁盤或網絡訪問)異步運行。

在.NET 4.5中使用async/await原語指令。

如果在線程池隊列中檢索到排隊任務時沒有線程可用,則線程池將增加線程數。如果這種趨勢在服務器中繼續存在,您可能會以線程池飢餓結束。在線程池隊列中充滿任務的情況下.net將拒絕更多請求,因此您將處於應用程序可擴展性的極限。

await指令將在您的應用程序中生成一個工作流程,釋放主線程。長時間運行操作完成後,一個新任務會在線程池中排隊,自動讓應用程序恢復。以這種方式釋放和回收線程將使當前邏輯線程的數量保持在最低水平,從而防止線程之間的飢餓和上下文切換。

也在.NET 4中。5新算法控制線程池內新線程創建的成本/收益,當趨勢增加時,在性能增加和上下文切換之間保持合理關係。如果你已經沒有這樣做,那麼這是一個額外的好處。

因此,第一步是確定您的長時間運行的操作,然後使它們異步。

您可以通過將當前邏輯線程數與其他計數器(數據庫客戶端連接,磁盤IO讀取等)相關聯來驗證此情況。如果第一次增加時其他人增加,你很可能確定這是問題所在。同時檢查操作需要多長時間。 100毫秒是一個很好的衡量標準,說明您的操作在一般意義上是長期運行的。

希望得到這個幫助。