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); }
public async Task Limit(DownloadConnection connection) { if ((Limited <= 0) || !IsActive) { return; } Tuple <long, DateTime> lastInfo = null; var limited = (float)Limited; lock (this) { if (!_connections.ContainsKey(connection)) { _connections.Add(connection, new Tuple <long, DateTime>(connection.TotalDownloaded, DateTime.Now)); } else { lastInfo = _connections[connection]; } foreach (var c in _connections.Keys.ToArray()) { if (c.Status != DownloadConnectionStatus.Downloading) { _connections.Remove(c); } } limited /= _connections.Count; } if (lastInfo != null) { // First limit by parent var limit = ParentLimiter?.Limit(connection); if (limit != null) { await limit; } // Calculate elapsed time since last sample var elapsed = (int)(DateTime.Now - lastInfo.Item2).TotalMilliseconds; // Calculate downloaded bytes since last sample var downloaded = connection.TotalDownloaded - lastInfo.Item1; // Calculate expected delay var delay = (int)(1000f * (downloaded / limited)) - elapsed; //System.Diagnostics.Debug.WriteLine("{0}ms - {1}b => {2}ms (+{3}ms)", elapsed, downloaded, delay + elapsed, delay); // Skip this time as we cant seriously expect a delay lower than 50ms if ((delay < 50) && (delay > 0)) { return; } lock (this) { if (_connections.ContainsKey(connection)) { _connections[connection] = new Tuple <long, DateTime>(connection.TotalDownloaded, DateTime.Now.AddMilliseconds(delay >= 50 ? delay : 0)); } } // Sleep for the calculated time if it is higher than 50ms and ignore it completely if it is lower than zero if (delay >= 50) { await Task.Delay(delay); } } }