c# - 使用具有最大值的 FluentFTP 从 FTP 同时下载多个文件

标签 c# multithreading concurrency ftp fluentftp

我想从 FTP 目录递归下载多个下载文件,为此我使用 FluentFTP 库,我的代码是这个:

private async Task downloadRecursively(string src, string dest, FtpClient ftp)
{

    foreach(var item in ftp.GetListing(src))
    {
        if (item.Type == FtpFileSystemObjectType.Directory)
        {
            if (item.Size != 0)
            {
                System.IO.Directory.CreateDirectory(Path.Combine(dest, item.Name));
                downloadRecursively(Path.Combine(src, item.Name), Path.Combine(dest, item.Name), ftp);
            }
        }
        else if (item.Type == FtpFileSystemObjectType.File)
        {
            await ftp.DownloadFileAsync(Path.Combine(dest, item.Name), Path.Combine(src, item.Name));
        }
    }
}

我知道您每次下载都需要一个 FtpClient,但是我怎样才能最大程度地使用一定数量的连接,我想这个想法是为我找到的每个文件创建、连接、下载和关闭,但只是同时下载 X 个文件。此外,我不确定是否应该使用异步、线程和我最大的问题创建任务,即如何实现所有这些。

来自 @Bradley 的回答这里看起来不错,但问题确实读取了必须从外部文件下载的每个文件,并且它没有最大并发下载值,所以我不确定如何应用这两个要求。

最佳答案

使用:

var clients = new ConcurrentBag<FtpClient>();

var opts = new ParallelOptions { MaxDegreeOfParallelism = maxConnections };
Parallel.ForEach(files, opts, file =>
{
    file = Path.GetFileName(file);

    string thread = $"Thread {Thread.CurrentThread.ManagedThreadId}";
    if (!clients.TryTake(out var client))
    {
        Console.WriteLine($"{thread} Opening connection...");
        client = new FtpClient(host, user, pass);
        client.Connect();
        Console.WriteLine($"{thread} Opened connection {client.GetHashCode()}.");
    }

    string remotePath = sourcePath + "/" + file;
    string localPath = Path.Combine(destPath, file);
    string desc =
        $"{thread}, Connection {client.GetHashCode()}, " +
        $"File {remotePath} => {localPath}";
    Console.WriteLine($"{desc} - Starting...");
    client.DownloadFile(localPath, remotePath);
    Console.WriteLine($"{desc} - Done.");

    clients.Add(client);
});

Console.WriteLine($"Closing {clients.Count} connections");
foreach (var client in clients)
{
    Console.WriteLine($"Closing connection {client.GetHashCode()}");
    client.Dispose();
}

另一种方法是启动固定数量的线程,每个线程有一个连接,并让它们从队列中挑选文件。

有关实现示例,请参阅我关于 WinSCP .NET 程序集的文章:
Automating transfers in parallel connections over SFTP/FTP protocol


关于 SFTP 的类似问题:
Processing SFTP files using C# Parallel.ForEach loop not processing downloads

关于c# - 使用具有最大值的 FluentFTP 从 FTP 同时下载多个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66241158/

相关文章:

c# - ConcurrentBag 的正确用法是什么?

c# - 将代码中的数据库表首先转换为模型的最佳方法

c# - 系统托盘中的 .Net 控制台应用程序

c# - 自动将 System.diagnostics.trace 消息记录到 Nlog 目标

c# - 重定向到超过文件上传大小的错误

c++ - C++ 中的互斥量必须绑定(bind)到某个对象或变量吗?

java - 多线程java中的一进一出要求与统一服务员要求

c++ - 我可以在单独的线程上刷新我的 ofstream 吗?

java - 所有这些默认线程都应该运行吗?它们能让我的 JVM 保持活力吗?

goroutine 等待 channel 的响应并继续