简体   繁体   English

SSH.Net异步文件下载

[英]SSH.Net Async file download

I am trying to download files asynchronously from an SFTP-server using SSH.NET. 我试图使用SSH.NET从SFTP服务器异步下载文件。 If I do it synchronously, it works fine but when I do it async, I get empty files. 如果我同步执行它,它工作正常,但当我执行异步时,我得到空文件。 This is my code: 这是我的代码:

var port = 22;
string host = "localhost";
string username = "user";
string password = "password";
string localPath = @"C:\temp";

using (var client = new SftpClient(host, port, username, password))
{
    client.Connect();
    var files = client.ListDirectory("");

    var tasks = new List<Task>();

    foreach (var file in files)
    {                        
        using (var saveFile = File.OpenWrite(localPath + "\\" + file.Name))
        {
            //sftp.DownloadFile(file.FullName,saveFile); <-- This works fine
            tasks.Add(Task.Factory.FromAsync(client.BeginDownloadFile(file.FullName, saveFile), client.EndDownloadFile));
        }                        
    }

    await Task.WhenAll(tasks);
    client.Disconnect();

}

Because saveFile is declared in a using block, it is closed right after you start the task, so the download can't complete. 因为saveFile是在using块中声明的,所以在启动任务后它立即关闭,因此下载无法完成。 Actually, I'm surprised you're not getting an exception. 实际上,我很惊讶你没有得到例外。

You could extract the code to download to a separate method like this: 您可以提取代码以下载到这样的单独方法:

var port = 22;
string host = "localhost";
string username = "user";
string password = "password";
string localPath = @"C:\temp";

using (var client = new SftpClient(host, port, username, password))
{
    client.Connect();
    var files = client.ListDirectory("");

    var tasks = new List<Task>();

    foreach (var file in files)
    {                        
        tasks.Add(DownloadFileAsync(file.FullName, localPath + "\\" + file.Name));
    }

    await Task.WhenAll(tasks);
    client.Disconnect();

}

...

async Task DownloadFileAsync(string source, string destination)
{
    using (var saveFile = File.OpenWrite(destination))
    {
        var task = Task.Factory.FromAsync(client.BeginDownloadFile(source, saveFile), client.EndDownloadFile);
        await task;
    }
}

This way, the file isn't closed before you finish downloading the file. 这样,在下载文件之前,文件不会关闭。


Looking at the SSH.NET source code, it looks like the async version of DownloadFile isn't using "real" async IO (using IO completion port), but instead just executes the download in a new thread. 看看SSH.NET源代码,看起来像DownloadFile的异步版本没有使用“真正的”异步IO(使用IO完成端口),而只是在新线程中执行下载。 So there's no real advantage in using BeginDownloadFile / EndDownloadFile ; 因此使用BeginDownloadFile / EndDownloadFile没有任何实际优势; you might as well use DownloadFile in a thread that you create yourself: 您也可以在自己创建的主题中使用DownloadFile

Task DownloadFileAsync(string source, string destination)
{
    return Task.Run(() =>
    {
        using (var saveFile = File.OpenWrite(destination))
        {
            client.DownloadFile(source, saveFile);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM