SSH.Net异步文件下载 [英] SSH.Net Async file download
问题描述
我正在尝试使用SSH.NET从SFTP服务器异步下载文件.如果我以同步方式进行操作,则可以正常工作,但是如果以异步方式进行操作,则会得到空文件.这是我的代码:
I am trying to download files asynchronously from an SFTP-server using SSH.NET. 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();
}
推荐答案
由于saveFile
在using
块中声明,因此在您开始执行任务后便立即将其关闭,因此无法完成下载.实际上,令您惊讶的是,我很惊讶.
Because saveFile
is declared in a using
block, it is closed right after you start the task, so the download can't complete. 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.
查看SSH.NET源代码,看起来DownloadFile
的异步版本未使用真正的"异步IO(使用IO完成端口),而是仅在新线程中执行下载.因此,使用BeginDownloadFile
/EndDownloadFile
并没有真正的优势.您最好在自己创建的线程中使用DownloadFile
:
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. So there's no real advantage in using BeginDownloadFile
/EndDownloadFile
; you might as well use DownloadFile
in a thread that you create yourself:
Task DownloadFileAsync(string source, string destination)
{
return Task.Run(() =>
{
using (var saveFile = File.OpenWrite(destination))
{
client.DownloadFile(source, saveFile);
}
}
}
这篇关于SSH.Net异步文件下载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!