private void Thread_Failed(object sender, ThreadExitedArgs e) { bool isRaiseFailed = false; lock (this._syncRoot) { if (e.WorkID != this._workID) { return; // 这次操作已经过期 } if (this._status != DownloaderStatuses.Downloading) { return; // 只有Downloading状态才可能变为Failed状态 } this.RefreshWorkID(); this._status = DownloaderStatuses.Failed; this._progressTimer.Dispose(); this._progressTimer = null; this.ClearThread(); this.CacheConfig();// 保存文件配置以便以后继续下载 this._sourceProvider = null; this._writer.Dispose(); this._writer = null; isRaiseFailed = true; }// lock if (isRaiseFailed) { this.OnFailed(); } }
/// <summary> /// 暂停,可以调用Start继续下载 /// </summary> public void Pause() { lock (this._syncRoot) { if (this._status != DownloaderStatuses.Downloading) { return; } this._status = DownloaderStatuses.Paused; // 刷新WorkID this.RefreshWorkID(); this._progressTimer.Dispose(); this._progressTimer = null; this.ClearThread(); // 缓存配置文件 this.CacheConfig(); // 清空SourceProvider this._sourceProvider = null; // 释放Writer this._writer.Dispose(); this._writer = null; }// lock this.OnPaused(); }
public SegmentThread(int id, LocalFileWriter writer, SourceProvider sourceProvider, long workID) { this._id = id; this._writer = writer; this._sourceProvider = sourceProvider; this._status = SegmentThreadStatuses.Idle; this._workID = workID; }
private void Thread_Completed(object sender, ThreadExitedArgs e) { bool isRaiseCompleted = false; lock (this._syncRoot) { if (e.WorkID != this._workID) { return; // 这次操作已经过期 } if (this._status != DownloaderStatuses.Downloading) { return; // 只有Downloading状态才可能变为Failed状态 } if (!this._writer.IsCompleted()) { return; // 文件下载还没有完成 } this.RefreshWorkID(); this._status = DownloaderStatuses.Completed; this._progressTimer.Dispose(); this._progressTimer = null; this.ClearThread(); this._sourceProvider = null; this._writer.Dispose(); this._writer = null; if (File.Exists(this._savePath)) { File.Delete(this._savePath); } File.Move(this._tmpPath, this._savePath); if (File.Exists(this._configPath)) { File.Delete(this._configPath); } isRaiseCompleted = true; }// lock if (isRaiseCompleted) { this.OnCompleted(); } }
/// <summary> /// 取消,会删除已经下载的文件 /// </summary> public void Cancel() { lock (this._syncRoot) { if (this._status == DownloaderStatuses.Completed) { return; // 如果已经下载完成则Cancel无效 } if (this._status == DownloaderStatuses.Cancelled) { return; // 如果已经取消了,则不能重复操作 } if (this._status == DownloaderStatuses.Downloading) { // 刷新WorkID this.RefreshWorkID(); this._progressTimer.Dispose(); this._progressTimer = null; this.ClearThread(); // 清空SourceProvider this._sourceProvider = null; // 释放Writer this._writer.Dispose(); this._writer = null; }// if this._status = DownloaderStatuses.Cancelled; // 删除临时文件 if (File.Exists(this._tmpPath)) { File.Delete(this._tmpPath); } // 删除配置文件 if (File.Exists(this._configPath)) { File.Delete(this._configPath); } }// lock this.OnCancelled(); }
/// <summary> /// 开始下载 /// </summary> public async void Start() { long workID; SourceProvider sourceProvider; lock (this._syncRoot) { if (this._status == DownloaderStatuses.Downloading) { throw new Exception("Downloader is working."); } if (this._status == DownloaderStatuses.Completed) { throw new Exception("Downloader is completed."); } this._status = DownloaderStatuses.Downloading; // 设置Downloader状态 // 生成新的workID workID = this.RefreshWorkID(); // 重置SourceProvider var protocalProvider = new HttpProtocalProvider(); var mirrorSelector = new SequentialMirrorSelector(); mirrorSelector.Initialize(this._config.MainSource, this._config.Mirrors); sourceProvider = new SourceProvider(mirrorSelector, protocalProvider); this._sourceProvider = sourceProvider; }// lock // 初始化SourceProvider await sourceProvider.InitializeAsync(CancellationToken.None); lock (this._syncRoot) { // 检测当前操作是否过期 if (workID != this._workID) { return; } var newRemoteFileInfo = this._sourceProvider.GetRemoteFileInfo(); // 对文件进行分片 List <LocalSegment> segments = new List <LocalSegment>(); if (this._config.HasSegment && this._config.RemoteInfo != null && RemoteFileInfo.IsSameFile(this._config.RemoteInfo, newRemoteFileInfo)) { // 如果文件已经分片,服务器文件信息与缓存的文件信息一致则用缓存的文件分片 segments.AddRange(this._config.Segments); } // 如果没有分片或则缓存的文件已经过时了则重新分片 if (segments.Count == 0) { if (newRemoteFileInfo.IsAcceptRange)// 如果文件支持分段下载 { var calculateSegments = this._segmentCalculator.GetSegments(this._maxThreadCount, newRemoteFileInfo); foreach (var calculateSegment in calculateSegments) { segments.Add(new LocalSegment { StartPosition = calculateSegment.StartPosition, EndPosition = calculateSegment.EndPosition }); } } else// 如果文件不支持分段下载 { if (newRemoteFileInfo.Size <= 0) { throw new Exception(string.Format("Remote file size invalid, size: {0}.", newRemoteFileInfo.Size)); } // 整个文件只有一个片段 segments.Add(new LocalSegment { StartPosition = 0, EndPosition = newRemoteFileInfo.Size - 1 }); // 设置最大线程数为1 this._maxThreadCount = 1; } // else } // if // 创建LocalFileWriter this._writer = new LocalFileWriter(this._tmpPath, segments, this._cacheLength); this._writer.CreateFile(); // 缓存文件配置 this.CacheConfig(); // 创建下载线程 this._threads = new List <SegmentThread>(); for (int i = 0; i < this._maxThreadCount; i++) { var thread = new SegmentThread(i + 1, this._writer, this._sourceProvider, workID); thread.Completed += Thread_Completed; thread.Failed += Thread_Failed; this._threads.Add(thread); } // 启动下载线程 foreach (var thread in this._threads) { thread.Start(); } this._lastProgressChangeTime = DateTime.Now; this._lastDownloadedSize = this._writer.GetDownloadedSize(); this._progressTimer = new Timer(ProgressTimer_Callback, workID, ProgressTimerInterval, Timeout.Infinite); }// lock this.OnStarted(); }