1616
1717using Microsoft . Extensions . Logging ;
1818
19+ // ReSharper disable once CheckNamespace
1920namespace dotnetCampus . FileDownloader ;
2021
2122/// <summary>
@@ -61,7 +62,7 @@ public SegmentFileDownloaderByHttpClient(string url, FileInfo file,
6162 _shouldDisposeHttpClient = httpClient is null ;
6263 HttpClient = httpClient ?? CreateDefaultHttpClient ( ) ;
6364
64- DownloadDataList = Channel . CreateUnbounded < DownloadData > ( new UnboundedChannelOptions ( )
65+ DownloadDataChannel = Channel . CreateUnbounded < DownloadData > ( new UnboundedChannelOptions ( )
6566 {
6667 SingleReader = false ,
6768 AllowSynchronousContinuations = true ,
@@ -135,6 +136,12 @@ private static SocketsHttpHandler CreateDefaultSocketsHttpHandler()
135136 //{
136137 // return ValueTask.FromResult(context.PlaintextStream);
137138 //}
139+
140+ // 忽略证书错误
141+ //SslOptions =
142+ //{
143+ // RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true
144+ //}
138145 } ;
139146
140147 return socketsHttpHandler ;
@@ -163,12 +170,12 @@ private static SocketsHttpHandler CreateDefaultSocketsHttpHandler()
163170 /// </summary>
164171 public string Url { get ; }
165172
166- private Channel < DownloadData > DownloadDataList { get ; }
173+ private Channel < DownloadData > DownloadDataChannel { get ; }
167174
168175 /// <summary>
169- /// 被加入到 <see cref="DownloadDataList "/> 的下载数量
176+ /// 被加入到 <see cref="DownloadDataChannel "/> 的下载数量
170177 /// </summary>
171- private int _workTaskCount ;
178+ private int _workingTaskCount ;
172179
173180 /// <summary>
174181 /// 下载的文件
@@ -233,7 +240,7 @@ private async void ControlSwitch()
233240 {
234241 LogDebugInternal ( "Start ControlSwitch" ) ;
235242 var ( segment , runCount , maxReportTime ) = SegmentManager . GetMaxWaitReportTimeDownloadSegmentStatus ( ) ;
236- var waitCount = _workTaskCount ;
243+ var waitCount = _workingTaskCount ;
237244
238245 LogDebugInternal ( "ControlSwitch 当前等待数量:{0},待命最大响应时间:{1},运行数量:{2},运行线程{3}" , waitCount , maxReportTime , runCount , _threadCount ) ;
239246
@@ -320,10 +327,13 @@ public async ValueTask DownloadFileAsync()
320327 return ;
321328 }
322329
323- FileStream = File . Create ( ) ;
324- FileStream . SetLength ( contentLength ) ;
330+ FileStream = File . Open ( FileMode . OpenOrCreate , FileAccess . ReadWrite , FileShare . Read /*允许边下边播*/ ) ;
331+ if ( FileStream . Length == 0 )
332+ {
333+ // 如果是刚刚创建的,则预先分配空间。实际测试下载器预先分配空间能够获取更好的机械硬盘性能
334+ FileStream . SetLength ( contentLength ) ;
335+ }
325336 FileWriter = new RandomFileWriterWithOrderFirst ( FileStream ) ;
326- FileWriter . StepWriteFinished += ( sender , args ) => SharedArrayPool . Return ( args . Data ) ;
327337
328338 if ( BreakpointResumptionTransmissionRecordFile is null )
329339 {
@@ -333,11 +343,13 @@ public async ValueTask DownloadFileAsync()
333343 else
334344 {
335345 // 有断点续传
336- var manager = new BreakpointResumptionTransmissionManager ( BreakpointResumptionTransmissionRecordFile , FileWriter , contentLength ) ;
346+ var manager = new BreakpointResumptionTransmissionManager ( BreakpointResumptionTransmissionRecordFile , FileWriter , SharedArrayPool , contentLength , BufferLength ) ;
337347 // 有断点续传情况下,先读取断点续传文件,通过此文件获取到需要下载的内容
338- SegmentManager = manager . CreateSegmentManager ( ) ;
348+ SegmentManager = await manager . CreateSegmentManagerAsync ( FileStream ) ;
339349 BreakpointResumptionTransmissionManager = manager ;
340350 }
351+ // 由于 BreakpointResumptionTransmissionManager 也在监控 StepWriteFinished 事件,如果这里的事件加等更快执行,则会导致数据已经还给了池,被其他地方使用,在 BreakpointResumptionTransmissionManager 存在线程安全
352+ FileWriter . StepWriteFinished += ( sender , args ) => SharedArrayPool . Return ( args . Data ) ;
341353
342354 _progress . Report ( new DownloadProgress ( $ "file length = { contentLength } ", SegmentManager ) ) ;
343355
@@ -559,15 +571,20 @@ private async ValueTask DownloadTask()
559571 DownloadData data ;
560572 try
561573 {
562- var canRead = await DownloadDataList . Reader . WaitToReadAsync ( ) ;
574+ var canRead = await DownloadDataChannel . Reader . WaitToReadAsync ( ) ;
563575 if ( ! canRead )
564576 {
565577 // 不能读取了,那就返回吧
566578 return ;
567579 }
568580
569- data = await DownloadDataList . Reader . ReadAsync ( ) . ConfigureAwait ( false ) ;
570- Interlocked . Decrement ( ref _workTaskCount ) ;
581+ if ( ! DownloadDataChannel . Reader . TryRead ( out data ) )
582+ {
583+ // 居然读取不到数据,那就再次进入循环吧
584+ continue ;
585+ }
586+
587+ Interlocked . Decrement ( ref _workingTaskCount ) ;
571588 }
572589 catch ( ChannelClosedException )
573590 {
@@ -712,8 +729,8 @@ private void LogDownloadSegment(DownloadSegment downloadSegment)
712729 private async void Download ( HttpResponseMessage ? httpResponseMessage , DownloadSegment downloadSegment )
713730 {
714731 LogDebugInternal ( "[Download] Enqueue Download. {0}" , downloadSegment ) ;
715- await DownloadDataList . Writer . WriteAsync ( new DownloadData ( httpResponseMessage , downloadSegment ) ) . ConfigureAwait ( false ) ;
716- Interlocked . Increment ( ref _workTaskCount ) ;
732+ await DownloadDataChannel . Writer . WriteAsync ( new DownloadData ( httpResponseMessage , downloadSegment ) ) . ConfigureAwait ( false ) ;
733+ Interlocked . Increment ( ref _workingTaskCount ) ;
717734 }
718735
719736 private void Download ( DownloadSegment ? downloadSegment )
@@ -748,7 +765,7 @@ private async ValueTask FinishDownload()
748765 await FileWriter . DisposeAsync ( ) . ConfigureAwait ( false ) ;
749766 await FileStream . DisposeAsync ( ) . ConfigureAwait ( false ) ;
750767
751- DownloadDataList . Writer . Complete ( ) ;
768+ DownloadDataChannel . Writer . Complete ( ) ;
752769
753770 BreakpointResumptionTransmissionManager ? . Dispose ( ) ;
754771 // 默认下载完成删除断点续传文件
0 commit comments