/// <summary> /// 检查是否下载完成 /// </summary> /// <param name="speedCalculator"></param> /// <param name="cancellationToken"></param> /// <returns></returns> private async Task <int> CheckDownloadInfoAsync(SpeedCalculator speedCalculator, CancellationToken cancellationToken) { var retryTasks = new List <DownloadTask>(); var retryCount = 0; int errorCount = 0; Func <DownloadSegmentInfo, bool> predicate = GetCheckDownloadSegmentInfoFunc(); while ((errorCount = DownloadInfo.Count(predicate)) > 0) { if (retryCount >= 3) { break; } Console.WriteLine($"错误数据个数:{errorCount},开始第{retryCount}次重试"); foreach (var item in DownloadInfo) { if (predicate(item)) { item.SrcStream = null; var task = DownloadSegmentFileAsync(item, (r, percentage) => { speedCalculator.CurrentValue += r; }, cancellationToken); retryTasks.Add(task); } } await retryTasks.StartAndWaitAllThrottled(MaxThreadCount); retryCount++; } return(errorCount); }
/// <summary> /// 下载文件 /// </summary> /// <param name="progressAction"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task DownloadFileAsync(Action <ProgressInfo> progressAction, CancellationToken cancellationToken = default) { if (IsDownloaded) { return; } SpeedCalculator speedCalculator = new SpeedCalculator(); ProgressInfo progressInfo = new ProgressInfo(); bool isCompleted = false; speedCalculator.Updated += async(h) => { progressInfo.AverageSpeed = speedCalculator.AverageSpeed; progressInfo.CurrentValue = speedCalculator.CurrentValue; progressInfo.Speed = speedCalculator.Speed; progressInfo.Percentage = DownloadInfo.Percentage; progressInfo.TargetValue = DownloadInfo?.Size; progressAction.Invoke(progressInfo); var count = DownloadInfo.Count(m => m.Size == 0); //Console.WriteLine("count " + count + " size " + DownloadInfo.Size + " read size " + DownloadInfo.TotalReadBytes); if (isCompleted) { speedCalculator.Stop(); } else { await SaveDownloadInfoAsync(); } }; foreach (var segment in DownloadInfo) { if (segment.TotalReadBytes != 0 && segment.TotalReadBytes >= segment.Size) { continue; } var task = DownloadSegmentFileAsync(segment, (r, percentage) => { speedCalculator.CurrentValue += r; }, cancellationToken); FileSegmentaionTasks.Add(task); } speedCalculator.Start(); await FileSegmentaionTasks.StartAndWaitAllThrottled(MaxThreadCount); var errorCount = await CheckDownloadInfoAsync(speedCalculator, cancellationToken); ///错误数量 if (errorCount == 0) { await ReconstructSegmentsAsync(); await CompleteAsync(true); } isCompleted = true; }