2014-10-07 173 views
1

我有一個以預定方式運行作業的控制檯應用程序。 作業做兩件事情:多線程應用程序和潛在內存泄漏(C#)

1)運行SQL語句 2-)的E-mail聲明

如果我運行順序形式的工作,一切按預期工作,工作的結果運行時,內存消耗會在操作期間增加,然後釋放內存,但是如果我並行運行作業,使用任務並行庫,在所有作業完成後,與順序選項相比,內存消耗會保持高得多,並且還會繼續執行其他作業增加內存消耗。

要我用下面的試驗例更具體的:

依序:(後循環完成,GC被明確地收集用於測試目的的內存消耗是大約55兆字節)

for (int j = 0; j < 3; j++) 
{ 
    for (int i = 0; i < 15; i++) 
    { 
     var job = new BIJob(reportData); 
     job.Execute(); 
    } 
    Thread.Sleep(10000); 
} 

並行: (循環完成後,顯式收集GC以用於測試目的內存消耗約爲85兆字節)

for (int j = 0; j < 3; j++) 
{ 
    for (int i = 0; i < 15; i++) 
    { 
     Task jobRunTask = Task.Factory.StartNew(() => 
     { 
      var job = new BIJob(reportData); 
      job.Execute(); 

     }); 
    } 
    Thread.Sleep(10000); 
} 

有近似值經過45次迭代後內存消耗差異達到30兆字節,並且並行版本中沒有收集額外的內存。

什麼可能導致這種行爲?任何想法/意見表示讚賞。

+0

您確定您的'job.Execute()'可以處理多線程場景嗎? – Natxo 2014-10-07 16:45:23

回答

1

當你並行執行多個操作時,你需要存儲足夠的內存來處理這些並行操作中的每一個,而不是每次在內存中只有一個工作集。您還有其他線程,每個線程都將消耗內存。

這些操作的內存將不能被回收,直到它們實際完成。你只是開始你的循環中的操作,而不是等待他們完成,所以他們不一定有資格收集,只要你是在檢查他們。如果您等待所有的操作到實際上完成那麼他們將合格收集,雖然GC當然是免費等待,只要實際上收集他們。

+0

您好Servy,我修改了我的並行代碼,以等待任務如下finsh;但是仍然大約相同,那麼所有任務完成: 'List tasks = new List (); 對(INT J = 0;Ĵ<3; J ++){ 爲 (INT I = 0; I <15;我++){ 任務 = jobRunTask Task.Factory.StartNew(()=> { 變種job = new BIJob(reportData); job.Execute(); }); tasks.Add(jobRunTask); } Thread.Sleep(10000); } Task.WaitAll(tasks.ToArray()); ' – erdem 2014-10-07 16:40:02

+1

@ erdem在任務完成後,內存變爲*合格*用於收集,但不一定會立即收集,並且創建的線程池線程在完成使用後不會立即被拆除;隨着時間的推移,他們會慢慢釋放。首先,你甚至不應該擔心這一點。如果你的記憶力確實有問題,你應該只關心自己,而你顯然不是。 – Servy 2014-10-07 16:42:58

+0

事情是我使用應用程序作爲服務,我每天都在觀看內存使用情況。在一批作業同時運行(大約10兆字節)之後,內存消耗量似乎每天都會增加很少,並且從未下降到之前的情況。 (我認爲那時候那些任務相關的資源應該已經發布了)。從長遠來看,這可能會導致崩潰問題。 – erdem 2014-10-07 16:54:46

0

任務並行庫將簡單地保留它創建的一些線程,以防它稍後需要它們,因爲創建新線程是相對昂貴的操作(無論是在內存和CPU方面)。

關於內存泄漏:只要資源沒有壓力,TPL就沒有理由使用線程池釋放任何線程。 如果你想測試一個內存泄漏,你可以簡單地增加你的循環次數。循環1000次或1000000次後,內存使用率應該沒有差別。

+0

這是線程池,而不是TPL,還要注意線程在閒置一段時間後會被釋放。 – Servy 2014-10-07 16:33:42

+0

默認的TPL使用線程池。是的,當然它會在一段時間後釋放它們。 – Foxfire 2014-10-07 16:37:38

+0

是的,我的觀點是這不是特定於TPL的行爲,它比這更普遍化,TPL只是使用具有此行爲的線程池。 – Servy 2014-10-07 16:39:47