Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中使用多线程时出现内存不足异常#_C#_Multithreading_Out Of Memory - Fatal编程技术网

C# 在C中使用多线程时出现内存不足异常#

C# 在C中使用多线程时出现内存不足异常#,c#,multithreading,out-of-memory,C#,Multithreading,Out Of Memory,我是线程新手,在这个问题上我被困在这里。我有一个使用多线程的应用程序。我有一个功能,上传上千的ftp服务器上的图像。对于每个图像,我创建一个新的线程。此线程调用一个函数来连接ftp服务器,上载文件,如果文件上载成功,则返回布尔值 我的问题是,由于我上传了数千张图片,每一张都在创建自己的线程,所以在某个时候我出现了内存异常和应用程序冻结 我的代码如下: public Int16 UploadFiles(string[] files) { foreach (var fileName in

我是线程新手,在这个问题上我被困在这里。我有一个使用多线程的应用程序。我有一个功能,上传上千的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个。

尝试将UploadFile(string[]文件)中的foreach替换为调用DownloadFileNow而不是UploadFile(string file)方法的Parallel.foreach()

Foreach将从线程池中提取线程,这是您想要的,并将简化您的代码

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

尝试用调用DownloadFileNow而不是UploadFile(string file)方法的Parallel.foreach()替换UploadFiles(string[]文件)中的foreach

Foreach将从线程池中提取线程,这是您想要的,并将简化您的代码

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

你不能创建这么多线程。另一种选择是使用parrelle扩展

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

你不能创建这么多线程。另一种选择是使用parrelle扩展

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

正如其他人所指出的,您不应该创建那么多线程。现在
Parallel.ForEach()
将为您提供良好的语法支持,您应该这样做

只是想指出,您需要将线程池作为一个概念来查找。看,让大量线程并行运行是没有意义的。对于每一个这样的任务,都有一个最佳的线程数量,超过这个数量,整个线程开销实际上会开始降低您的速度。或者,在你的情况下,耗尽你所有的记忆

如果你把这项任务想象成一堆放在桌子上的照片(文件夹)和为你跑腿的员工的线程,那么让一名员工从桌子上拿一张照片,把它放在信封里,然后带到邮局,对于每一张照片,这将是一个漫长的过程。所以你雇佣了另一名员工。还有一个。但是,一旦你接触到一定数量的照片邮递员,他们就会开始互相阻碍。他们在桌子前排队。他们在邮局前排队。整个信封的情况对负责办公用品的可怜的玛丽来说是痛苦的——他们也在她面前排队!因此,找出最佳员工数量(你可以运行测试或只是猜测一下),并分配他们重复该任务,直到办公桌空了为止


这是一种经常出现的主/从模式

正如其他人所指出的,您不应该创建那么多线程。现在
Parallel.ForEach()
将为您提供良好的语法支持,您应该这样做

只是想指出,您需要将线程池作为一个概念来查找。看,让大量线程并行运行是没有意义的。对于每一个这样的任务,都有一个最佳的线程数量,超过这个数量,整个线程开销实际上会开始降低您的速度。或者,在你的情况下,耗尽你所有的记忆

如果你把这项任务想象成一堆放在桌子上的照片(文件夹)和为你跑腿的员工的线程,那么让一名员工从桌子上拿一张照片,把它放在信封里,然后带到邮局,对于每一张照片,这将是一个漫长的过程。所以你雇佣了另一名员工。还有一个。但是,一旦你接触到一定数量的照片邮递员,他们就会开始互相阻碍。他们在桌子前排队。他们在邮局前排队。整个信封的情况对负责办公用品的可怜的玛丽来说是痛苦的——他们也在她面前排队!因此,找出最佳员工数量(你可以运行测试或只是猜测一下),并分配他们重复该任务,直到办公桌空了为止


这是一种经常出现的主/从模式

);这就是为什么你会出错。正如下面的答案所建议的那样,你需要使用第三方物流。建立一种队列,限制你一次可以下载多少东西。也许可以尝试使用任务而不是线程,这样您就可以知道,当使用超过(8*个逻辑_处理器)线程的Windows进程出现问题时,它们将无法执行或扩展。例如,一个带有服务应用程序的单CPU系统使用超过8个线程来处理请求(例如套接字接受),将很快使这个盒子屈服。@DanielBullington-什么?我是从Firefox-57线程发布的。我的i7有4/8个内核。卡巴斯基AV有92个线程。NT内核和系统有257个线程。“超过(8个逻辑_处理器)”的谬误从何而来?OP的问题是不断创建/终止/销毁线程,而不是将任务提交到线程池。对于主要在I/O上阻塞的网络任务,池中的64个线程并非不合理。;这就是为什么你会出错。正如下面的答案所建议的那样,你需要使用第三方物流。建立一种队列,限制你一次可以下载多少东西。也许可以尝试使用任务而不是线程,这样您就可以知道,当使用超过(8*个逻辑_处理器)线程的Windows进程出现问题时,它们将无法执行或扩展。例如,一个带有服务应用程序的单CPU系统使用超过8个线程来处理请求(例如套接字接受),将很快使这个盒子屈服。@DanielBullington-什么?我是从Firefox-57线程发布的。我的i7有4/8个内核。卡巴斯基AV有92个线程。NT内核和系统有257个线程。你从哪里得到的不止这些