【发布时间】:2013-07-25 15:28:29
【问题描述】:
我是线程新手,在这个问题上卡在这里。我有一个使用多线程的应用程序。我有一个在 ftp 服务器上上传数千张图像的功能。对于每个图像,我正在创建一个新线程。该线程调用函数连接ftp服务器,上传文件,上传成功返回布尔值。
我的问题是,由于我要上传数千张图片,并且每张图片都在创建自己的线程,所以在一段时间后我遇到内存不足异常并且应用程序冻结。
我的代码如下:
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 个。
【问题讨论】:
-
a thread uses 1MB of memory;这就是你得到错误的原因。您需要改用 TPL,如下面的答案所示。
-
创建一种队列,限制一次可以下载多少东西。也许尝试使用任务而不是线程,这样您就可以知道它们何时完成
-
任何使用超过 (8 * logical_processors) 线程的 Windows 进程都将无法执行或扩展。例如,具有使用超过 8 个线程来处理请求(例如套接字接受)的服务应用程序的单 CPU 系统,将很快让盒子屈服。
-
@DanielBullington - 什么?我从 Firefox 发布这个 - 57 个线程。我的 i7 有 4/8 核。 Kaspersky AV 有 92 个线程。 NT 内核和系统有 257 个线程。你从哪里得到“超过(8 * logical_processors)”的谬误?
-
OP 的问题是不断创建/终止/销毁线程,而不是将任务提交到线程池。对于大部分在 I/O 上被阻塞的联网任务,池中 64 个线程并不是不合理的。
标签: c# multithreading out-of-memory