Itaketedue
Itaketedue

Reputation: 21

Why can I only do 2 concurrent downloads with the .NET GDrive API v3?

I'm not sure if this is a client or an API limitation, but I can't seem to do more than 2 concurrent downloads with the .NET GDrive API. This causes a big problem for my application, because if the user wants to download more than 2 files at once, all the other "queued" downloads will timeout eventually if the first 2 downloads aren't completed in time, which will also raise a System.Threading.Tasks.TaskWasCanceled in my case, since I'm using FilesResource.GetRequest.DownloadAsync.

Is there some sort of property that I can change to allow more than 2 concurrent downloads, or to increase the timeout before it raises an exception?

Here's my current download function:

public static async Task DownloadFile(string name, string downloadPath, string extractPath, string appExePath, GridButton clickedGridBtn)
{
    name += ".zip";
    downloadPath += ".zip";

    foreach (Google.Apis.Drive.v3.Data.File gDriveFile in filesList)
    {
        if (!gDriveFile.Name.Equals(name))
            continue;

        Utils.CreateDirIfNotExist(ConfigUtils.downloadPath);

        clickedGridBtn.Btn.IsEnabled = false;

        DownloadProgressPanel dlProgressPanel = new DownloadProgressPanel() { AppIconPath = $"/Resources/Icons/{name.Replace(".zip", string.Empty)}" };
        UIElementCollection dlProgressWindowChildren = MainWindow.Instance.DlProgressPanelStack.Children;
        bool alreadyExists = false;

        foreach (DownloadProgressPanel dlPanel in dlProgressWindowChildren)
        {
            if (dlPanel.AppIconPath.Equals(dlProgressPanel.AppIconPath))
            {
                int index = dlProgressWindowChildren.IndexOf(dlPanel);

                dlProgressWindowChildren.RemoveAt(index);
                dlProgressWindowChildren.Insert(index, dlProgressPanel);

                alreadyExists = true;
                break;
            }
        }

        if (!alreadyExists)
            dlProgressWindowChildren.Add(dlProgressPanel);

        MainWindow.Instance.TabButton_Click(MainWindow.Instance.DownloadsTabBtn);

        FileStream dlFileStream = new FileStream(downloadPath, FileMode.OpenOrCreate);

        FilesResource.GetRequest fileReq = service.Files.Get(gDriveFile.Id);
        long? fileSize = gDriveFile.Size;

        dlProgressPanel.DownloadSizeText.Text = $"Downloading... 0 MB of {Utils.ConvertToGigabytes(fileSize)}";
        dlProgressPanel.DLProgressBar.Value = Utils.ConvertToPercentage(0.0, (double)fileSize);

        fileReq.MediaDownloader.ChunkSize = 204800;
        fileReq.MediaDownloader.ProgressChanged += (IDownloadProgress progress) =>
        {
            switch (progress.Status)
            {
                case DownloadStatus.Downloading:
                    UpdateProgressValues(progress, fileSize, dlProgressPanel);
                    break;
                case DownloadStatus.Completed:
                    UpdateProgressValues(progress, fileSize, dlProgressPanel);

                    dlFileStream.Dispose();
                    dlFileStream.Close();

                    DownloadCompleted(dlProgressPanel, clickedGridBtn, downloadPath, extractPath, appExePath);
                    break;
                case DownloadStatus.Failed:
                    Console.WriteLine($"Failed to download \"{name}\"!");
                    break;
            }
        };

        await fileReq.DownloadAsync(dlFileStream);
        break;
    }
}

If I need to provide any other details, please tell me!

Upvotes: 1

Views: 69

Answers (1)

Itaketedue
Itaketedue

Reputation: 21

Looks like you can set the service's HttpClient.Timeout property, which fixed my issue. I still can't do more than 2 concurrent downloads, but this is enough. My main issue was my function raising the TaskWasCanceled exception. If anybody knows how to allow more than 2 concurrent downloads, please comment on this answer! Either way, here's an e.g. of setting the timeout (assuming service is your new DriveService instance):

service = new DriveService(new BaseClientService.Initializer()
{
    HttpClientInitializer = gDriveUserCredential,
    ApplicationName = ApplicationName
});
service.HttpClient.Timeout = Timeout.InfiniteTimeSpan;

EDIT: Thanks to @Evk for the concurrent downloads fix. Setting the ServicePointManager.DefaultConnectionLimit property at the startup of my application seems to work just fine, e.g:

ServicePointManager.DefaultConnectionLimit = 4;

Upvotes: 1

Related Questions