2015-12-02 10 views
6

Ich versuche, Dateien asynchron von einem SFTP-Server mit SSH.NET herunterladen. Wenn ich es synchron mache, funktioniert es gut, aber wenn ich es async mache, bekomme ich leere Dateien. Dies ist mein Code:SSH.Net Async-Datei herunterladen

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

} 

Antwort

7

Da saveFile in einem using Block deklariert wird, wird es geschlossen rechts, nachdem Sie die Aufgabe starten, so dass der Download kann nicht abgeschlossen werden. Eigentlich bin ich überrascht, dass Sie keine Ausnahme bekommen.

Sie könnten den Code extrahieren in eine separate Methode wie folgt herunterladen:

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

Auf diese Weise wird die Datei nicht geschlossen, bevor Sie die Datei fertig heruntergeladen.


Mit Blick auf der SSH.NET Quellcode, es sieht aus wie die Asynchron-Version von DownloadFile ist nicht "real" async IO (mit IO Completion-Port) verwenden, sondern führt nur den Download in einem neuen Thread . Es gibt also keinen wirklichen Vorteil bei der Verwendung von BeginDownloadFile/EndDownloadFile; Sie könnte genauso gut DownloadFile in einem Thread verwenden, die Sie selbst erstellen:

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

@YuvalItzchakov, fest, danke! –

+0

Vielen Dank für die Antwort, aber ich bekomme immer noch die gleichen leeren Dateien, wenn ich das versuche. Keine Ausnahme auch nicht. – spersson

+2

@spersson, habe ich meine Antwort aktualisiert. Es scheint, dass es keinen Vorteil gibt, 'BeginDownloadFile' zu ​​verwenden, also können Sie auch die synchrone Version verwenden. –

Verwandte Themen