未附加VS调试器时Task.WhenAll()异常:HttpClient超时设置解决
Task.WhenAll()异步下载Google Drive文件夹的异常问题
在异步编程中使用Task.WhenAll()批量下载Google Drive文件夹时遇到以下异常问题:
- 附加Visual Studio调试器运行:下载约1000个文件耗时22-25秒,全程正常
- 未附加调试器运行:耗时增至2分钟以上,同时抛出
System.Threading.Tasks.TaskCanceledException异常
文件夹下载核心代码
public static async Task<bool> DownloadFolder(CloudDataModel.File file, string path, params string[] exclude) { try { if (file != null && !string.IsNullOrEmpty(file.id)) { List<string> toExclude = new List<string>(); if(exclude != null) { toExclude = exclude.ToList(); } List<Task> downloadFilesTask = new List<Task>(); var files = await file.GetFiles(); foreach (var f in files) { var task = f.Download(path); downloadFilesTask.Add(task); } var folders = await file.GetFoldersAsync(); foreach (var folder in folders) { if (toExclude.Contains(folder.name)) { continue; } Task task = null; if (path.Equals(Statics.ProjectFolderName)) { task = DownloadFolder(folder, folder.name); } else { task = DownloadFolder(folder, Path.Combine(path, folder.name)); } downloadFilesTask.Add(task); } var array = downloadFilesTask.ToArray(); await Task.WhenAll(array); return true; } } catch (Exception e) { Crashes.TrackError(e); } return false; }
问题根源:单个文件下载方法
经排查,异常由文件下载方法DownloadFile引发,核心代码如下:
public static async Task<StorageFile> DownloadFile(CloudDataModel.File file, string destinationFolder) { try { if (file != null) { Debug.WriteLine($"start download {file.name}"); if (file.mimeType == Statics.GoogleDriveFolderMimeType) { Debug.WriteLine($"did not download resource, resource was folder instead of file. mimeType: {file.mimeType}"); return null; } var endpoint = Path.Combine(DownloadFileEndpoint, $"{file.id}?alt=media"); // 此处引发异常行为 HttpResponseMessage response = await client.GetAsync(endpoint); StorageFile downloadedFile; using (Stream streamToReadFrom = await response.Content.ReadAsStreamAsync()) { var memstream = new MemoryStream(); StreamReader reader = new StreamReader(streamToReadFrom); streamToReadFrom.Position = 0; await streamToReadFrom.CopyToAsync(memstream); downloadedFile = await fileHandler.SaveDownloadedCloudFile(memstream, file, destinationFolder); Debug.WriteLine($"download finished {file.name}"); } return downloadedFile; } return null; } catch (Exception e) { Crashes.TrackError(e); return null; } }
解决方案
为System.Net.Http.HttpClient设置超时时间后,代码执行恢复正常:
client.Timeout = new TimeSpan(0,0,5);
内容的提问来源于stack exchange,提问作者Rick Bieze
相关产品推荐
相关产品推荐

