2013-07-25 65 views
1

我是線程新手,並且在此問題上停留在此處。我有一個應用程序,我正在使用多線程。我有一個上傳ftp服務器上數以千計的圖像的功能。對於每個圖像我創建一個新的線程。這個線程調用一個函數來連接ftp服務器,上傳文件並返回布爾值,如果它成功上傳的話。在C中使用多線程時出現內存不足異常#

我的問題是,因爲我上傳了成千上萬的圖像,並且每個圖像都創建了自己的線程,所以在某段時間內出現內存不足異常和應用程序死機。

我的代碼如下:

public Int16 UploadFiles(string[] files) 
{ 
    foreach (var fileName in files) 
     { 
      if (UploadFile(fileName)) 
      { 
       strLogText += "\r\n\tFile: " + fileName + " downloaded."; 
      } 
     } 
} 

private bool UploadFile(string fileName) 
    { 
     var blnDownload = false; 
     var thread = new Thread(() => DownLoadFileNow(fileName, out blnDownload)) {IsBackground = true}; 
     thread.Start(); 
     return blnDownload; 
    } 

    private void DownLoadFileNow(string fileName, out bool blnDownload) 
    { 
     //Get file path and name on source ftp server 
     var srcFolder = GetSrcFolderName(fileName); 

     //Get Local Folder Name for downloaded files 
     var trgFolder = GetLocalFolder(fileName, "D"); 

     var reqFtp = 
      (FtpWebRequest) WebRequest.Create(new Uri("ftp://" + _strSourceFtpurl + srcFolder + "/" + fileName)); 
     reqFtp.Method = WebRequestMethods.Ftp.DownloadFile; 
     reqFtp.UseBinary = true; 
     reqFtp.Credentials = new NetworkCredential(_strSourceFtpUser, _strSourceFtpPassword); 
     var outputStream = new FileStream(trgFolder + "\\" + fileName, FileMode.Create); 

     try 
     { 
      var response = (FtpWebResponse) reqFtp.GetResponse(); 
      var ftpStream = response.GetResponseStream(); 
      const int bufferSize = 2048; 
      var buffer = new byte[bufferSize]; 

      if (ftpStream != null) 
      { 
       int readCount = ftpStream.Read(buffer, 0, bufferSize); 
       while (readCount > 0) 
       { 
        outputStream.Write(buffer, 0, readCount); 
        readCount = ftpStream.Read(buffer, 0, bufferSize); 
       } 

       ftpStream.Close(); 
      } 
      response.Close(); 
      blnDownload = true; 
     } 
     catch (WebException ex) 
     { 
      _log.WriteLog("Error in Downloading File (" + fileName + "):\r\n\t" + ex.Message, ""); 
      //Delete newly created file from local system 
      outputStream.Close(); 
      if (File.Exists(trgFolder + "/" + fileName)) 
       File.Delete(trgFolder + "/" + fileName); 
     } 
     catch (Exception ex) 
     { 
      _log.WriteLog("Error in Downloading File (" + fileName + "):\r\n\t" + ex.Message, ""); 
     } 
     finally 
     { 
      outputStream.Close(); 
      outputStream.Dispose(); 
     } 
     blnDownload = false; 
    } 

請幫助,讓我知道我怎麼能限制所創建的線程數量,以便在同一時間,有運行中的不超過10-20個線程。

+1

[一個線程使用1MB內存](http://msdn.microsoft.com/en-us/library/windows/desktop/ms686774(v = vs.85).aspx);這就是你得到錯誤的原因。您需要使用TPL來代替,如下面的答案中所述。 – GolfWolf

+0

製作一種隊列,限制你一次可以下載多少東西。也許嘗試使用任務而不是線程,這樣你可以知道它們何時完成 – Robert

+0

任何使用多於(8 * logical_processors)線程的Windows進程將無法執行或縮放。例如,具有使用多於8個線程來處理請求(例如套接字接受)的服務應用程序的單個CPU系統將迅速將該框放在膝蓋上。 –

回答

2

嘗試使用調用DownloadFileNow而不是UploadFile(String file)方法的Parallel.ForEach()替換UploadFiles(string []文件)中的foreach。

Parallel.Foreach將從線程池中提取線程,這是您想要的,並且會簡化您的代碼。

Parallel.ForEach(files, fileName => 
     DownloadFileNow(fileName); 
     strLogText += "\r\n\tFile: " + fileName + " downloaded."; 
); 
+0

謝謝,我現在正在「AggregateException未處理」。任何想法如何解決這個問題? – sarojanand

+0

我敢打賭,它必須以異步方式更新strLogText。你用strLogText做什麼? – user467384

+0

我使用在函數末尾的日誌文件中添加以知道上載了多少個文件和哪些文件。而不是每次添加,我將它們添加到字符串中,並在每個循環結束後添加日誌文件。 – sarojanand

3

你不能創建這麼多的線程。另一種選擇是使用parrelle擴展。

public void UploadFiles(string[] files) 
{ 
    files.AsParallel().ForAll(fileName => 
    { 
     if (UploadFile(fileName)) 
     { 
      strLogText += "\r\n\tFile: " + fileName + " downloaded."; 
     } 
    }); 
} 
1

正如其他人指出的,你不應該創造這麼多的線程。現在... Parallel.ForEach()會給你很好的語法糖,你應該走這條路!

只是想指出,你需要查找線程池作爲一個概念。看到,大量的線程並行運行是沒有意義的。對於每個這樣的任務,都有一個最佳的線程數量,超過這個線程,整個線程開銷實際上會開始減慢你的速度。或者,在你的情況下,用盡你所有的記憶。

如果您將任務視爲一堆照片坐在桌子上(文件夾)和線程作爲員工爲您跑腿跑步,然後讓一名員工從桌子上拿取照片,放入信封中將它帶到郵局,爲每張照片,將永遠持續下去。所以你僱用另一名員工。另一個。但是,一旦你達到了一定數量的照片郵寄員,他們開始採取其他方式。他們排在桌前。他們排在郵局前。整個信封情況對於負責辦公用品的可憐瑪麗來說是痛苦的 - 他們也在她面前排隊等候!因此,找出最佳員工數量(您可以運行測試或者只是猜測一下),然後指定他們重複該任務,直到辦公桌空着...

這是一個主/從模式,經常。

相關問題