2015-12-02 189 views
6

我试图使用SSH.NET从SFTP服务器异步下载文件。如果我同步执行,它可以正常工作,但是当我执行异步时,我会得到空文件。这是我的代码:SSH.Net异步文件下载

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(); 

} 

回答

7

因为saveFileusing块宣布,它已关闭启动任务之后,就可以下载无法完成。其实,我很惊讶你没有得到一个例外。

你可以提取代码下载到这样一个单独的方法:

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; 
    } 
} 

这样一来,该文件未关闭你下载完文件之前。


望着SSH.NET源代码,它看起来像的DownloadFile异步版本没有使用“真正的”异步IO(使用IO完成端口),而只是执行下载在一个新的线程。所以在使用BeginDownloadFile/EndDownloadFile时没有真正的优势;你不妨在你自己创建的主题中使用DownloadFile

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

@YuvalItzchakov,修正了,谢谢! –

+0

谢谢你的回答,但是,当我尝试这个时,我仍然得到相同的空文件。也没有例外。 – spersson

+2

@spersson,我更新了我的答案。看起来使用'BeginDownloadFile'没有优势,所以你最好使用同步版本。 –