s sh. net сеанс операции throw истек и завис - PullRequest
0 голосов
/ 16 июня 2020

Я создал оконную службу, которая использует S SH. net для чтения файла с sFTP-сервера каждые 600 секунд в OnStart. Я создаю таймер

timer = new Timer(TimerCallback, null, 0, timeDelay);

, а TimerCallBack - это функция, использующая S SH . net. При подключении перед чтением файла у меня есть код для подключения к sFTP-серверу, как показано ниже

            var FILE_READ_FLAG = false;
            try
            {
                req = new SftpClient(ftpHost, ftpLogin, ftpLoginPassword);
                req.Connect();
                if (req.IsConnected)
                {
                    directories = req.ListDirectory(ftpPath);
                    FILE_READ_FLAG = true;
                }
            }
            catch (Exception e)
            {

                EventLog.WriteEntry(sSource,"ERROR : " + GetFullMessageFromException(e), 
                                    EventLogEntryType.Information, 234);
                
                FILE_READ_FLAG = false;
            }
            if (FILE_READ_FLAG){
               // read file and insert to database
            }

проблема в том, что когда служба запускается и возникает исключение, служба может запускаться снова каждые 600 секунд, но с ошибкой

Session operation has timed out
   at Renci.SshNet.Session.WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout)
   at Renci.SshNet.Session.WaitOnHandle(WaitHandle waitHandle)
   at Renci.SshNet.Session.Connect()
   at Renci.SshNet.BaseClient.Connect()

служба не может работать снова и кажется, что она зависла, когда я пытаюсь остановить и перезапустить службу, Windows показать предупреждающее сообщение не может быть своевременно остановлено, и мне нужно убить службу с помощью cmd и запустить ее вручную

Мой вопрос в том, почему другое исключение может обрабатываться с помощью блока try / catch, но с этой ошибкой служба не запускается снова с таймером, которого я пропустил или использовал неправильно? спасибо

1 Ответ

1 голос
/ 22 июня 2020

Вы создали объект SftpClient . Глядя на код, он не удаляется должным образом, а также вы не вызываете отключение. Возможно, в случае ошибки система зависнет из-за открытого соединения.

Однако вы устанавливаете клиент как переменную (т.е. req = new SftpClient(ftpHost, ftpLogin, ftpLoginPassword), поэтому его возможное отключение / удаление вызывается в другом месте . Хотя я бы по-прежнему рекомендовал реструктурировать код, чтобы вы получали данные от клиента SFTP, а они немедленно отключались / удалялись. Рекомендуется минимизировать время, в течение которого соединение открыто.

Учтите следующее:

List<SftpFile> files = null; 
using (SftpClient sftp = new SftpClient(host, username, password)) // using will dispose SftpClient
{
    try
    {
        sftp.Connect();    
        files = sftp.ListDirectory(ftpPath).ToList();    
        sftp.Disconnect();
    }
    catch (Exception e)
    {
        EventLog.WriteEntry(sSource,"ERROR : " + GetFullMessageFromException(e), 
                                EventLogEntryType.Information, 234);
    }
}

if(files.any())
{
   // Process the files.
}
...