/// <summary> /// Wraps the downloadToStream logic to retry/recover the download operation /// in the case that the last time the input stream has been written to exceeds a threshold. /// </summary> /// <param name="stream"></param> /// <param name="blobOffset"></param> /// <param name="length"></param> /// <param name="accessCondition"></param> /// <param name="options"></param> /// <param name="operationContext"></param> /// <param name="cancellationToken"></param> /// <returns></returns> private async Task downloadToStreamWrapper(UnmanagedMemoryStream stream, long blobOffset, long length, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { long startingOffset = blobOffset; LargeDownloadStream largeDownloadStream = null; while (true) { try { largeDownloadStream = new LargeDownloadStream(stream, blobOffset); CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(largeDownloadStream.CancellationToken, cancellationToken); Task downloadTask = this.LargeDownloadToFileSettings.Blob.DownloadRangeToStreamAsync(largeDownloadStream, blobOffset, length, this.accessConditions, this.blobRequestOptions, this.operationContext, cts.Token); await downloadTask; largeDownloadStream.Close(); break; } catch (OperationCanceledException) // only catch if the stream triggered the cancellation when(!cancellationToken.IsCancellationRequested) { blobOffset = startingOffset + largeDownloadStream.Position; largeDownloadStream.Close(); length -= (blobOffset - startingOffset); Console.WriteLine($"cancellation for offset:{startingOffset}, now at position:{blobOffset}. With remaining length:{length}"); if (length == 0) { break; } } } stream.Dispose(); }
public LargeDownloadRange(Task downloadTask, LargeDownloadStream largeDownloadStream, long blobOffSet, long rangeLength) { this.DownloadTask = downloadTask; this.LargeDownloadStream = largeDownloadStream; this.BlobOffset = blobOffSet; this.RangeLength = rangeLength; }