如何在循环中完成任何任务后,将值传递给另一个方法,return 到循环中,并等待下一个任务完成?

How after completing any task in the loop, pass a value to another method, return to the loop, and wait for the next task to complete?

2 种方法一种方法依赖于另一种方法。我需要并行发送几个文件到服务器,服务器的回答首先出现,然后将其发送到 DownloadFileAsync 方法,对其余的做同样的事情(不要一次等待所有答案,发送它们(来自服务器的答案)到 DownloadFileAsync() 方法,因为他们收到了)。

public async Task CompressAllFilesAsync(List<UserFile> files, string outputpath)
{
    await UploadAllFilesAsync(files);
    await DownloadAllFilesAsync(files, outputpath);
}

public async Task UploadAllFilesAsync(List<UserFile> files)
{
    IEnumerable<Task> allTasks = files.Select(async (file, i) =>
        files[i].FileLink = await UploadFileAsync(files[i])
    );

    await Task.WhenAll(allTasks);
}

public async Task DownloadAllFilesAsync(List<UserFile> files, string outputpath)
{
    IEnumerable<Task> allTasks = files.Select((file, i) =>
        DownloadFileAsync(files[i].FileLink,
        Path.Combine(outputpath, $"{files[i].FileName}")
    ));

    await Task.WhenAll(allTasks);
}

现在程序在 运行 DownloadAllFilesAsync() 方法之前等待服务器的所有答复(可下载文件的链接)。

for (int i = 0; i < fileToSend; i++)
{    
   Task task = new Task(() => 
   {
      SendFile(file[i]);
   });
   task.Start();
}

通过这种方式,您将创建一个并行发送文件的后台任务

您可以考虑使用新的 (.NET 6) API Parallel.ForEachAsync,并依次为每个 [=14= 执行 UploadFileAsyncDownloadFileAsync ],但同时与其他文件:

public async Task CompressAllFilesAsync(List<UserFile> files, string outputPath)
{
    var options = new ParallelOptions() { MaxDegreeOfParallelism = 10 };
    await Parallel.ForEachAsync(files, options, async (file, ct) =>
    {
        await UploadFileAsync(file);
        await DownloadFileAsync(file.FileLink,
            Path.Combine(outputPath, $"{file.FileName}"));
    });
}

UploadFileAsyncDownloadFileAsync 将在 ThreadPool 个线程上调用。这应该不是问题,除非这些方法与 thread-affine 组件(如 UI 控件)交互。

public async Task CompressAllFilesAsync(List<UserFile> files, string outputpath) {
    SemaphoreSlim throttler = new SemaphoreSlim(2);

    IEnumerable<Task> allTasks = files.Select(async (file) => {
        await throttler.WaitAsync();

        try {
            file.Link = await UploadFileAsync(file);

            await DownloadFileAsync(file.Link,
                Path.Combine(outputpath, file.Name));
        } finally {
            throttler.Release();
        }
    });

    await Task.WhenAll(allTasks);
}