2016-01-25 37 views
0

我在運行一些非常簡單的代碼時遇到意外的行爲。使用ThreadPool的System.OutOfMemoryException

首先我使用Visual Studio 2015年i7-4770的CPU,32GB存儲(22,6免費)

我的示例代碼:

 int length = 10; 

     for (int i = 0; i < length; i++) 
     { 
      int j = i; 
      //ThreadPool.QueueUserWorkItem(ThreadProc_CLR, j); 
      Task.Factory.StartNew(() => { ThreadProc_CLR(j); }); 
     } 

     public void ThreadProc_CLR(object parameter) 
     { 
      int i = Convert.ToInt32(parameter); 

      byte[] data = new byte[1000000000]; 
      new Random().NextBytes(data); 
      System.Security.Cryptography.SHA1.Create().ComputeHash(data); 

     } 

我不明白的是爲什麼我辦使用

  • 平臺目標我的代碼:任何CPU
  • 身高32位選中

我得到一個System.OutOfMemoryException分配字節[]緩衝區的第三或第四的時間

如果我取消後「首選32位」一切工作順利進行。我一直在尋找任何文檔解釋可能的限制,但我還沒有找到任何。

+4

32位表示您不能分配超過2GB的RAM。您的代碼嘗試分配10GB的RAM。 –

+0

當您完成時,您正在創建沒有[處理它們]的SHA1實例(https://msdn.microsoft.com/en-us/library/dd289076%28v=vs.110%29.aspx)。這可能是泄漏。 – spender

+0

@PanagiotisKanavos完全正確 - 每次迭代需要10億字節= 1 GB。 –

回答

2

看來您是在64位操作系統上運行。

當您使用「任何CPU」和「首選32位」設置編譯已開啓。然後,即使OS是64位,該進程也將以32位進程執行。

32位進程可以具有2GB大小的虛擬地址空間(可以是4GB使用LARGEADDRESSAWARE設置)。這比你的應用程序運行所需要的要少得多。你的應用似乎分配了大約10GB,並且密碼學API也將消耗一些內存。

當取消「不想32位」的設置,該過程將作爲一個64位的進程中運行。這爲您提供了8 TB的虛擬地址空間。

+0

所以基本上「喜歡的32位」是指「力的32位」。理解,謝謝你的反饋 – Stefano

0

你不處置的HashAlgorithm的實例,因此他們很可能坐着消耗的內存。

//... 
using(var ha = System.Security.Cryptography.SHA1.Create()) 
{ 
    ha.ComputeHash(data); 
} 
+0

雖然這在技術上是正確的,但它不是OP面臨的問題的根源。 – Heinzi

+0

@Hininzi:我不同意。如果OP在經過多次傳遞後內存不足,那麼是的,在32位進程中有足夠的內存來完成他們想要的任務。釋放它最有可能避免切換到64位的必要性。簡單地切換到64位而不理解代碼爲什麼會隱藏內存似乎對我來說短視。 – spender

+0

您可能忽略了OP使用線程:每個1GB的10個實例*並行啓動*。因此,即使這些實例正確地處置了它們的內存,32位地址空間從來就不夠(除非,巧合*,調度程序將這10個線程完全序列化,但這不太可能)。 – Heinzi