/// <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; }