/// <summary> /// 暂停下载 /// </summary> public void Pause() { lock (this._syncRoot) { if (this._cts == null) { return; } this._cts.Cancel(); this._cts = null; this._writer.UnregisterSegment(this._id); this._status = SegmentThreadStatuses.Paused; } this.OnPaused(new ThreadExitedArgs(this._workID)); }
/// <summary> /// 开始下载 /// </summary> public void Start() { var cts = new CancellationTokenSource(); lock (this._syncRoot) { if (this._cts != null) { cts.Dispose(); throw new Exception("The thread is running."); } this._cts = cts; this._status = SegmentThreadStatuses.Running; } Task.Run(() => { return(this.DownloadProc(cts)); }, cts.Token); }
/// <summary> /// 下载线程 /// </summary> /// <param name="cts">检测是否取消</param> /// <returns></returns> private async Task DownloadProc(CancellationTokenSource cts) { var ct = cts.Token; try { while (true)// 循环下载文件片段 { RegisteredSegment segment; lock (this._syncRoot) { ct.ThrowIfCancellationRequested(); // 检测是否取消下载 segment = this._writer.RegisterSegment(this._id); // 获取需要下载的片段 } if (segment == null) { break; // 注册的片段为null,证明下载已经完成或就快完成,这个线程已经获取不到任务了 } await this.DownloadSegment(segment, ct); // 下载片段 lock (this._syncRoot) { ct.ThrowIfCancellationRequested(); this._writer.UnregisterSegment(this._id);// 取消注册下载片段 } }// while // 设置线程状态为空闲 lock (this._syncRoot) { ct.ThrowIfCancellationRequested(); this._status = SegmentThreadStatuses.Idle; } } catch (OperationCanceledException) { // 线程状态在Stop方法中被设置为了Cancelled,这里就不用设置了 return;// 表示取消 } catch (Exception) { // 设置线程状态为失败 lock (this._syncRoot) { if (!ct.IsCancellationRequested) { this._status = SegmentThreadStatuses.Failed; } } return;// 出现未知异常,停止下载 } finally { bool isRaiseCompleted = false; bool isRaiseFailed = false; // 取消注册片段 lock (this._syncRoot) { if (!ct.IsCancellationRequested) { this._cts = null; this._writer.UnregisterSegment(this._id); isRaiseCompleted = this._status == SegmentThreadStatuses.Idle; isRaiseFailed = this._status == SegmentThreadStatuses.Failed; } } cts.Dispose();// 释放取消资源 if (isRaiseCompleted) { this.OnCompleted(new ThreadExitedArgs(this._workID)); } if (isRaiseFailed) { this.OnFailed(new ThreadExitedArgs(this._workID)); } }// finally }