SSH.Net 异步文件下载
SSH.Net Async file download
我正在尝试使用 SSH.NET 从 SFTP 服务器异步下载文件。如果我同步执行它,它工作正常但是当我异步执行时,我得到空文件。这是我的代码:
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
块中声明的,它会在您开始任务后立即关闭,因此下载无法完成。事实上,我很惊讶你没有得到例外。
您可以像这样提取代码以下载到单独的方法:
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
的异步版本没有使用 "real" 异步 IO(使用 IO 完成端口),而只是执行在新线程中下载。所以使用 BeginDownloadFile
/EndDownloadFile
没有真正的优势;您也可以在自己创建的线程中使用 DownloadFile
:
Task DownloadFileAsync(string source, string destination)
{
return Task.Run(() =>
{
using (var saveFile = File.OpenWrite(destination))
{
client.DownloadFile(source, saveFile);
}
}
}
我正在尝试使用 SSH.NET 从 SFTP 服务器异步下载文件。如果我同步执行它,它工作正常但是当我异步执行时,我得到空文件。这是我的代码:
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
块中声明的,它会在您开始任务后立即关闭,因此下载无法完成。事实上,我很惊讶你没有得到例外。
您可以像这样提取代码以下载到单独的方法:
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
的异步版本没有使用 "real" 异步 IO(使用 IO 完成端口),而只是执行在新线程中下载。所以使用 BeginDownloadFile
/EndDownloadFile
没有真正的优势;您也可以在自己创建的线程中使用 DownloadFile
:
Task DownloadFileAsync(string source, string destination)
{
return Task.Run(() =>
{
using (var saveFile = File.OpenWrite(destination))
{
client.DownloadFile(source, saveFile);
}
}
}