服务器断开连接后,C# 程序卡在 FtpWebResponse 中

C# Program gets stuck in FtpWebResponse after server disconnects

我有一个 C# 程序,每 x 秒检查一次 ftp 目录是否有新文件。如果找到新文件,则会下载该文件。那很好用。如果我在没有 运行 ftp 服务器的情况下启动程序,程序将循环并 returns 显示无法访问服务器的消息。然后我启动服务器,程序按预期连接。但是,如果我再次退出 ftp 服务器,我的程序就会卡在 FtpWebResponse 中。

我在 try catch 块中有一个 using 语句块来关闭所有连接。

while (true)
{
    //...
    FtpFileList = null;
    while (FtpFileList == null)
    {
        FtpFileList = await GetFtpFileList(adress, user, password);
        await Task.Delay(3000);
    }
    await Task.Delay(27000);
    //...
}


public static async Task<List<string>> GetFtpFileList(string address, string user, string password)
{
    try
    {
        List<string> returnValue = new List<string>();
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create(address);
        request.Method = WebRequestMethods.Ftp.ListDirectory;
        request.Credentials = new NetworkCredential(user, password);
        using (FtpWebResponse response = (FtpWebResponse)await request.GetResponseAsync()) //The program gets stuck here
        {
            Stream responseStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(responseStream);
            while (reader.Peek() >= 0)
            {
                returnValue.Add(reader.ReadLine());
            }
        }
        AddToLogFile(DateTime.Now + ": " + "FTP directory updated");
        return returnValue;
    }
    catch (WebException e)
    {
        AddToLogFile(DateTime.Now + ": " + e.Message);
        return null;
    }
}

我希望程序在连接丢失后重新连接到服务器,但它卡住了。

感谢任何帮助和提示如何解决该问题。

只是想让你知道,我通过实施变通方法解决了这个问题:我没有使用 await request.GetResponseAsync(),而是在另一个线程中使用普通的 GetResponse() 方法,该方法目前没有任何问题:await Task.Run(() => request.GetResponse())

使用 FtpWebRequest.GetResponse 而不是 FtpWebRequest.GetResponseAsync(因为 GetResponseAsyncFtpWebRequest 中没有被覆盖并且来自基础 WebRequest class,它似乎无法处理某些特定的 FTP 用例)

如果你需要等待一些东西,只需替换这个:

FtpWebRequest request = ...
var response = (FtpWebResponse) await request.GetResponseAsync();
return response;

这样:

var response = (FtpWebResponse) request.GetResponse();
return await Task.FromResult(response);