示例#1
0
        private DownloadConnection SpawnConnection(StreamVolume stream)
        {
            var connection = new DownloadConnection(Request, new DownloadRange(stream.Range.Start), stream, 0);

            connection.Completed += delegate(object sender, CompletedEventArgs args)
            {
                connection.Stream.Close();
                OnProgressChanged();
            };

            connection.ProgressChanged += delegate(object sender, EventArgs args)
            {
                OnProgressChanged();
            };

            connection.ResponseReceived += delegate(object sender, ResponseReceivedEventArgs args)
            {
                if (args.Response.SupportsRange)
                {
                    connection.Range = connection.Range.ShrinkLength(stream.Range.Length);
                }
            };
            lock (_connections)
            {
                _connections.Add(connection);
            }
            return(connection);
        }
示例#2
0
        public StreamVolume GetFreeVolume(long start, long maximumLength)
        {
            if (start >= TotalSize)
            {
                throw new ArgumentException("Start position is greater or equal to the total length.", nameof(start));
            }
            if (maximumLength == -1)
            {
                maximumLength = TotalSize - start;
            }
            var          volumes = Volumes.ToList();
            StreamVolume overlap;

            do
            {
                overlap = volumes.FirstOrDefault(volume => volume.Range.Contains(start));
                if (overlap != null)
                {
                    start = overlap.Range.End + 1;
                }
            } while (overlap != null);
            var end = Math.Min(start + maximumLength, TotalSize) - 1;

            do
            {
                overlap = volumes.FirstOrDefault(volume => volume.Range.Contains(end));
                if (overlap != null)
                {
                    end = overlap.Range.Start - 1;
                }
            } while (overlap != null);
            if (end >= start)
            {
                var volume = new StreamVolume(Stream, new StreamVolumeRange(start, end));
                lock (_volumes)
                {
                    _volumes.Add(volume);
                }
                return(volume);
            }
            return(null);
        }
示例#3
0
        public async Task Start(CancellationToken token)
        {
            var partSize          = 1024 * 1024 * 3;
            var nConnections      = 3;
            var splitPartition    = new StreamVolume(Partition.Stream, StreamVolumeRange.Empty);
            var initialConnection = SpawnConnection(splitPartition);
            var taskSource        = new TaskCompletionSource <DownloadResponse>();

            initialConnection.ResponseReceived += (sender, args) =>
            {
                if (OnResponseReceived(args.Response))
                {
                    args.Abort = true;
                    taskSource.SetCanceled();
                    return;
                }
                if (args.Response.SupportsRange)
                {
                    Partition.TotalSize = args.Response.FileSize;
                    Partition.Stream.SetLength(Partition.TotalSize);
                    var newRange = Partition.GetFreeVolume(0, partSize);
                    splitPartition.Range    = newRange.Range;
                    initialConnection.Range = newRange.Range;
                }
                taskSource.SetResult(args.Response);
            };
            var initialTask = initialConnection.Start(token);
            var response    = await taskSource.Task;

            if (!response.SupportsRange)
            {
                await Task.WhenAll(initialTask);

                if (initialTask.IsCanceled)
                {
                    // Canceled
                }
                return;
            }
            var connections = new List <Tuple <DownloadConnection, Task> >
            {
                new Tuple <DownloadConnection, Task>(initialConnection, initialTask)
            };
            StreamVolume range;

            do
            {
                range = Partition.GetFreeVolume(0, partSize);
                if (range != null)
                {
                    while (connections.Count(t => t.Item1.Status == DownloadConnectionStatus.Downloading) >=
                           nConnections)
                    {
                        await
                        Task.WhenAny(
                            connections.Where(t => t.Item1.Status == DownloadConnectionStatus.Downloading)
                            .Select(t => t.Item2)
                            .ToArray());
                    }
                    var connection = SpawnConnection(range);
                    var task       = connection.Start(token);
                    connections.Add(new Tuple <DownloadConnection, Task>(connection, task));
                }
            } while (!token.IsCancellationRequested && (range != null));
            await Task.WhenAll(connections.Select(t => t.Item2).ToArray());
        }