【问题标题】:Exception of type 'System.OutOfMemoryException' was thrown in a SFTP connection在 SFTP 连接中引发了“System.OutOfMemoryException”类型的异常
【发布时间】:2012-08-30 14:05:59
【问题描述】:

场景:我有一个与 SFTP 服务器建立连接并下载文件的应用程序。执行此操作的代码:

while (true)
{
    try
    {
        var connectionInfo = // creating a new connection info of a Renci.SshNet lib
        var client = new SftpClient(connectionInfo);
        client.Connect();

        using (SftpFileStream sftpFileStream = client.OpenRead(path)
        {
            using (FileStream fileStream = new FileStream(filePath, FileMode.CreateNew))
            {
                int BUFFER_SIZE = 2048;
                byte[] buffer = new byte[BUFFER_SIZE];

                int readBytes = sftpFileStream.Read(buffer, 0, BUFFER_SIZE);

                while (readBytes > 0)
                {
                    fileStream.Write(buffer, 0, readBytes);
                    readBytes = sftpFileStream.Read(buffer, 0, BUFFER_SIZE);
                }
            }
        }

        client.Dispose();
    }
    catch (Exception e)
    {
        log.Error(e);
    }

    Thread.Sleep(1 hour);
}

client.Connect() 行中出现了第一个错误:

Renci.SshNet.Common.SftpPathNotFoundException: No such file at Renci.SshNet.Sftp.SubsystemSession.WaitHandle(WaitHandle waitHandle, TimeSpan operationTimeout) at Renci.SshNet.Sftp.SftpSession.RequestOpen(String path, Flags flags, Boolean nullOnError) at Renci.SshNet.Sftp.SftpFileStream..ctor(SftpSession session, String path, FileMode mode, FileAccess access, Int32 bufferSize, Boolean useAsync) at Renci.SshNet.Sftp.SftpFileStream..ctor(SftpSession session, String path, FileMode mode, FileAccess access) at Renci.SshNet.SftpClient.OpenRead(String path) at Infraero.TINE3.STTColetor.Negocio.Drivers.DriverAbstratoArquivoFTP.BaixarArquivoPABXSFTP(ConfiguracaoColetor configuracaoColetor, String arquivoPABX) in D:\SVN\STT\trunk\3-0_CodigoFonte_Coletor\3-4_SRC\Infraero.TINE3.STTColetor.Negocio\Drivers\DriverAbstratoArquivoFTP.cs:line 446 at Infraero.TINE3.STTColetor.Negocio.Drivers.DriverAbstratoArquivoFTP.ProcessarArquivoSFTP(SftpFile arquivo, ConfiguracaoColetor configuracaoColetor, List'1 listaBilhetes) in D:\SVN\STT\trunk\3-0_CodigoFonte_Coletor\3-4_SRC\Infraero.TINE3.STTColetor.Negocio\Drivers\DriverAbstratoArquivoFTP.cs:line 658 at Infraero.TINE3.STTColetor.Negocio.Drivers.DriverAbstratoArquivoFTP.ColetarBilhetes(ConfiguracaoColetor configuracaoColetor, List'1 listaBilhetes, String ultimoArquivoTransmitido) in D:\SVN\STT\trunk\3-0_CodigoFonte_Coletor\3-4_SRC\Infraero.TINE3.STTColetor.Negocio\Drivers\DriverAbstratoArquivoFTP.cs:line 73 at Infraero.TINE3.STTColetor.Negocio.Coletor.ColetarBilhetes() in D:\SVN\STT\trunk\3-0_CodigoFonte_Coletor\3-4_SRC\Infraero.TINE3.STTColetor.Negocio\Coletor.cs:line 56 at Infraero.TINE3.STTColetor.WindowsService.ServicoColetor..ctor() in D:\SVN\STT\trunk\3-0_CodigoFonte_Coletor\3-4_SRC\Infraero.TINE3.STTColetor.WindowsService\ServicoColetor.cs:line 85

1 小时后,该过程再次尝试下载文件,但在client.Connect() 行出现新错误:

System.Threading.Tasks.TaskSchedulerException: An exception was thrown by a TaskScheduler. ---> System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. at System.Threading.Thread.StartInternal(IPrincipal principal, StackCrawlMark& stackMark) at System.Threading.Thread.Start(StackCrawlMark& stackMark) at System.Threading.Thread.Start(Object parameter) at System.Threading.Tasks.ThreadPoolTaskScheduler.QueueTask(Task task) at System.Threading.Tasks.Task.ScheduleAndStart(Boolean needsProtection) --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ScheduleAndStart(Boolean needsProtection) at System.Threading.Tasks.Task.InternalStartNew(Task creatingTask, Object action, Object state, CancellationToken cancellationToken, TaskScheduler scheduler, TaskCreationOptions options, InternalTaskOptions internalOptions, StackCrawlMark& stackMark) at System.Threading.Tasks.TaskFactory.StartNew(Action action, TaskCreationOptions creationOptions) at Renci.SshNet.Session.ExecuteThread(Action action) at Renci.SshNet.Session.Connect() at Renci.SshNet.BaseClient.Connect() at Infraero.TINE3.STTColetor.Negocio.Drivers.DriverAbstratoArquivoFTP.ConectarServidorSFTP(String servidor, Int32 porta, String login, String senha) in D:\SVN\STT\trunk\3-0_CodigoFonte_Coletor\3-4_SRC\Infraero.TINE3.STTColetor.Negocio\Drivers\DriverAbstratoArquivoFTP.cs:line 551 at Infraero.TINE3.STTColetor.Negocio.Drivers.DriverAbstratoArquivoFTP.RequisitarArquivoServidorSFTP(ConfiguracaoColetor configuracaoColetor) in D:\SVN\STT\trunk\3-0_CodigoFonte_Coletor\3-4_SRC\Infraero.TINE3.STTColetor.Negocio\Drivers\DriverAbstratoArquivoFTP.cs:line 519 at Infraero.TINE3.STTColetor.Negocio.Drivers.DriverAbstratoArquivoFTP.ColetarBilhetes(ConfiguracaoColetor configuracaoColetor, List'1 listaBilhetes, String ultimoArquivoTransmitido) in D:\SVN\STT\trunk\3-0_CodigoFonte_Coletor\3-4_SRC\Infraero.TINE3.STTColetor.Negocio\Drivers\DriverAbstratoArquivoFTP.cs:line 67 at Infraero.TINE3.STTColetor.Negocio.Coletor.ColetarBilhetes() in D:\SVN\STT\trunk\3-0_CodigoFonte_Coletor\3-4_SRC\Infraero.TINE3.STTColetor.Negocio\Coletor.cs:line 56 at Infraero.TINE3.STTColetor.WindowsService.ServicoColetor..ctor() in D:\SVN\STT\trunk\3-0_CodigoFonte_Coletor\3-4_SRC\Infraero.TINE3.STTColetor.WindowsService\ServicoColetor.cs:line 85

1天后,第二个错误继续,app的内存使用量从60MB增加到800MB。

有人知道问题出在哪里吗?

【问题讨论】:

  • 你确定第 85 行是client.Connect()
  • 是的,忽略错误中的行计数器,我提出问题的代码是所有代码的摘要。
  • 投反对票的人,你为什么对我的问题投反对票?
  • 只是为了让你知道这不是我,尽管我认为你不应该发布完整的堆栈跟踪。
  • @user919426 完成了!

标签: c# .net out-of-memory sftp


【解决方案1】:

快速浏览您正在使用的库的代码库 (http://sshnet.codeplex.com/SourceControl/changeset/view/18974) 表明 SftpClient 也实现了 IDisposable,但是当出现故障时您不会清理或关闭它。您应该尝试以下方法:

try
{
    var connectionInfo = // something
    using(var client = new SftpClient(connectionInfo))
    {
        client.Connect();
        using(var sftpFileStream = client.OpenRead(path))
        {
            // download the file
        }
    }
}

也可能是您正在使用的库内部存在内存泄漏。

【讨论】:

  • @ViniciusOttoni - 按照上面列出的代码方式,您不可能从 catch 块中调用 dispose,因为该变量将超出范围。我用一个例子更新了我的答案。
  • 使用 using 块,如果在您的答案的client.Connect() 行中引发错误,对象client 将被释放?
  • @ViniciusOttoni - 是的。不过,您可能需要仔细查看代码,看看是否需要完成任何其他清理工作。
猜你喜欢
  • 1970-01-01
  • 2015-07-12
  • 2013-01-14
  • 2013-08-28
  • 2015-07-18
  • 2011-02-14
相关资源
最近更新 更多