在继续处理之前,如何等待处理程序的响应?

时间:2019-10-27 21:19:31

标签: c# .net .net-core

我目前正在使用Google Drive的.NET API,并且正在尝试从驱动器中下载多个文件。可以在here(以下是我的版本)中找到Google在示例中使用的代码

在.NET Core控制台项目中,我遍历文件列表并尝试一次下载一个文件,例如:

foreach (var file in driveFiles) {
    var fileId = file.Id;
    var request = driveService.Files.Get(fileId);
    var stream = new System.IO.MemoryStream();

    // Add a handler which will be notified on progress changes.
    // It will notify on each chunk download and when the
    // download is completed or failed.
    request.MediaDownloader.ProgressChanged +=
        (IDownloadProgress progress) =>
    {
        switch (progress.Status)
        {
            case DownloadStatus.Downloading:
                {
                    Console.WriteLine(progress.BytesDownloaded);
                    break;
                }
            case DownloadStatus.Completed:
                {
                    Console.WriteLine("Download complete.");
                    break;
                }
            case DownloadStatus.Failed:
                {
                    Console.WriteLine("Download failed.");
                    break;
                }
        }
    };
    request.Download(stream);

    // .. carry on processing
}

我的问题是我有大约300个文件的列表。上面的代码同时触发了所有300次下载,我看到了每次下载的进度。我想要发生的是每次下载一次发生一次,即。我先关闭第一个下载,然后代码等待下载完成,然后再继续进行下一个下载。

我试图通过设置一个布尔值来做到这一点,该布尔值仅在下载完成或失败后才更新,但这似乎不起作用:

foreach (var file in driveFiles) {
        var fileId = file.Id;
        var request = driveService.Files.Get(fileId);
        var stream = new System.IO.MemoryStream();

        bool processingComplete = false;

        // Add a handler which will be notified on progress changes.
        // It will notify on each chunk download and when the
        // download is completed or failed.
        request.MediaDownloader.ProgressChanged +=
            (IDownloadProgress progress) =>
        {
            switch (progress.Status)
            {
                case DownloadStatus.Downloading:
                    {
                        Console.WriteLine(progress.BytesDownloaded);
                        break;
                    }
                case DownloadStatus.Completed:
                    {
                        Console.WriteLine("Download complete.");
                        processingComplete = true;
                        break;
                    }
                case DownloadStatus.Failed:
                    {
                        Console.WriteLine("Download failed.");
                        processingComplete = true;
                        break;
                    }
            }
        };
        request.Download(stream);

        while (!processingComplete) ;

        processingComplete = false;
    }

但是,这似乎不起作用,并且代码似乎继续具有相同的行为。

我对做什么感到困惑。有人有什么想法吗?

2 个答案:

答案 0 :(得分:0)

您的问题是您要为每个文件启动单独的任务。即使我无法弄清楚您的代码的哪一部分实际上在这里多任务处理。我看不到任何明显的问题,例如await,Threads之类。您需要执行循环的一项任务。基本上,您必须等待请求完成,然后再进行下一个练习。

通常,“按文件”多任务处理是没有好处的。通常,瓶颈是磁盘或网络之类的东西。联网是一种偶然的情况- 可能而且经常有益于同时下载多个文件,即使是从同一端点下载也是如此。使用google API,它们可能由不同的服务器(地理广播IIRC)提供服务,提供者端可能会设置带宽限制,等等。

答案 1 :(得分:0)

因此,根据法比奥的评论,似乎请求确实具有DownloadAsync方法。我已经实现了这一点,这似乎可以解决我的问题:

foreach (var file in driveFiles) {
        var fileId = file.Id;
        var request = driveService.Files.Get(fileId);
        var stream = new System.IO.MemoryStream();

        // Add a handler which will be notified on progress changes.
        // It will notify on each chunk download and when the
        // download is completed or failed.
        request.MediaDownloader.ProgressChanged +=
                (IDownloadProgress progress) =>
        {
                switch (progress.Status)
                {
                        case DownloadStatus.Downloading:
                                {
                                        Console.WriteLine(progress.BytesDownloaded);
                                        break;
                                }
                        case DownloadStatus.Completed:
                                {
                                        Console.WriteLine("Download complete.");
                                        break;
                                }
                        case DownloadStatus.Failed:
                                {
                                        Console.WriteLine("Download failed.");
                                        break;
                                }
                }
        };

        IDownloadProgress result = await request.DownloadAsync(stream);    
}
相关问题