我可以访问一个已连接的Renci.SshNet.SftpClient,用它来获取SFTP文件夹中文件的序列。此功能的名称为:
Renci.SshNet.SftpClient.ListDirectory(string);
由于目录中的文件数量很多,这需要大约7秒钟的时间。我希望能够使用async/await和cancellationToken使我的用户界面保持响应状态。
如果Renci.SshNet有一个返回任务的ListDirectoryAsync函数,那么这将变得容易起来:
async Task<IEnumerable<SftpFiles> GetFiles(SftpClient connectedSftpClient, CancellationToken token)
{
var listTask connectedSftpClient.ListDirectoryAsync();
while (!token.IsCancellatinRequested && !listTask.IsCompleted)
{
listTask.Wait(TimeSpan.FromSeconds(0.2);
}
token.ThrowIfCancellationRequested();
return await listTask;
}
遗憾的是,SftpClient没有异步函数。以下代码可以工作,但在下载过程中无法取消:
public async Task<IEnumerable<SftpFile>> GetFilesAsync(string folderName, CancellationToken token)
{
token.ThrowIfCancellationRequested();
return await Task.Run(() => GetFiles(folderName), token);
}
然而,SftpClient确实具有使用功能的异步功能。
public IAsyncResult BeginListDirectory(string path, AsyncCallback asyncCallback, object state, Action<int> listCallback = null);
Public IEnumerable<SftpFile> EndListDirectory(IAsyncResult asyncResult);
在文章“将IAsyncResult代码转换为新的async和await模式”中,描述了如何将IAsyncResult转换为await。
然而,我不知道如何处理BeginListdirectory中的所有参数以及放置EndListDirectory的位置。有人能将其转换为可等待的任务,以便我可以使用短时间间隔等待并检查取消标记吗?
BeginListDirectory
方法不接受CancellationToken
,因此ListDirectoryAsync
也不应该接受。有时候像这样的库会有另一种名为CancelListDirectory
或者Cancel
的方法来实现取消操作,在这种情况下,EndListDirectory
可能会抛出OperationCanceledException
异常。 - Stephen Cleary