![](/img/trans.png)
[英]Out of memory exception is throwing while using Substring method in C#
[英]out of memory exception while using multithread in C#
我是线程技术的新手,并在此问题上停留在这里。 我有一个使用多线程的应用程序。 我有一个功能,可以在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。
您不能创建这么多线程。 一种替代方法是使用parrelle扩展名。
public void UploadFiles(string[] files)
{
files.AsParallel().ForAll(fileName =>
{
if (UploadFile(fileName))
{
strLogText += "\r\n\tFile: " + fileName + " downloaded.";
}
});
}
尝试使用调用DownloadFileNow而不是UploadFile(String file)方法的Parallel.ForEach()替换UploadFiles(string [] files)中的foreach。
Parallel.Foreach将从您想要的线程池中提取线程,并简化您的代码。
Parallel.ForEach(files, fileName =>
DownloadFileNow(fileName);
strLogText += "\r\n\tFile: " + fileName + " downloaded.";
);
正如其他人指出的那样,您不应该创建那么多线程。 现在... Parallel.ForEach()
将为您提供不错的语法糖,您应该走那条路!
只是想指出,您需要将线程池视为一个概念。 看到,并行运行大量线程没有意义。 对于每个这样的任务,都有一个最佳线程数,超过该线程数时,整个线程开销实际上将开始使您变慢。 或者,就您而言,用尽所有内存。
如果您将任务想象成一堆坐在办公桌(文件夹)上的照片,而线程又像是员工为您办事的线程,那么请一位员工从办公桌上取一张照片,将其放在信封中并带到办公室。邮局,对于每张照片,将永远保留下去。 因此,您雇用了另一名员工。 还有一个。 但是,一旦您达到一定数量的照片邮递员,它们就会开始互相影响。 他们在办公桌前排队。 他们在邮局门口排队。 对于负责办公用品的可怜的玛丽来说,整个信封的状况简直令人痛苦-他们也在她的面前排队! 因此,找出最佳员工人数(您可以运行测试或猜测一下),然后分配他们重复执行此任务,直到办公桌空了为止。
这是一个经常出现的主/从模式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.