2017-03-10 136 views
-1
private void DownloadFile() { 

    if (_downloadUrls.Any()) { 
    WebClient client = new WebClient(); 
    client.DownloadProgressChanged += client_DownloadProgressChanged; 
    client.DownloadFileCompleted += client_DownloadFileCompleted; 

    var url = _downloadUrls.Dequeue(); 
    string startTag = "animated/"; 
    string endTag = "/infra"; 

    int index = url.IndexOf(startTag); 
    int index1 = url.IndexOf(endTag); 

    string fname = url.Substring(index + 9, index1 - index - 9); 
    client.DownloadFileAsync(new Uri(url), @"C:\Temp\tempframes\" + fname + ".gif"); 

    lastDownloadedFile = @"C:\Temp\tempframes\" + fname + ".gif"; 
    label1.Text = url; 
    return; 
    } 

    // End of the download 
    btnStart.Text = "Download Complete"; 
} 

private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { 
    if (e.Error != null) { 
    // handle error scenario 
    throw e.Error; 
    } 
    if (e.Cancelled) { 
    // handle cancelled scenario 
    } 

    Image img = new Bitmap(lastDownloadedFile); 
    Image[] frames = GetFramesFromAnimatedGIF(img); 
    foreach(Image image in frames) { 
    countFrames++; 
    image.Save(@"C:\Temp\tempframes\" + countFrames + ".gif"); 
    } 

    DownloadFile(); 
} 

void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { 
    double bytesIn = double.Parse(e.BytesReceived.ToString()); 
    double totalBytes = double.Parse(e.TotalBytesToReceive.ToString()); 
    double percentage = bytesIn/totalBytes * 100; 
    pBarFileProgress.Value = int.Parse(Math.Truncate(percentage).ToString()); 
    label1.Text = e.BytesReceived.ToString() + "/" + e.TotalBytesToReceive.ToString(); 
} 

現在我加入這個方法如何計算並顯示每個文件的下載速度?

DateTime lastUpdate; 
long lastBytes = 0; 

private void progressChanged(long bytes) { 
    if (lastBytes == 0) { 
    lastUpdate = DateTime.Now; 
    lastBytes = bytes; 
    return; 
    } 

    var now = DateTime.Now; 
    var timeSpan = now - lastUpdate; 
    var bytesChange = bytes - lastBytes; 
    var bytesPerSecond = bytesChange/timeSpan.Seconds; 

    lastBytes = bytes; 
    lastUpdate = now; 
} 

而且我想用這種方法或另一種方法在LABEL2的progresschanged事件顯示下載速度。但我不確定如何使用這種方法。

不確定如何在progresschanged事件中使用它。

+0

一般來說'每秒字節數=最後一個數據包中的字節數/自上一個數據包以來的秒數',以便看起來正確。平滑一點(例如通過保持最後10個值並顯示平均值),並獲得下載速度。 –

+0

@ManfredRadlwimmer如果你能告訴我該怎麼做?謝謝。 –

+1

當然,我會舉一個簡短的例子,馬上回來。 –

回答

1

您準備方法的調用progressChanged將最適合client_DownloadProgressChanged這樣的:

progressChanged(e.BytesReceived); 

然而,你必須使用TotalSeconds代替Seconds或值將不正確的,也是由零異常

導致分裂
var bytesPerSecond = bytesChange/timeSpan.TotalSeconds; 

這個助手類將保持跟蹤接收塊,時間戳和進步的你:

public class DownloadProgressTracker 
{ 
    private long _totalFileSize; 
    private readonly int _sampleSize; 
    private readonly TimeSpan _valueDelay; 

    private DateTime _lastUpdateCalculated; 
    private long _previousProgress; 

    private double _cachedSpeed; 

    private Queue<Tuple<DateTime, long>> _changes = new Queue<Tuple<DateTime, long>>(); 

    public DownloadProgressTracker(int sampleSize, TimeSpan valueDelay) 
    { 
     _lastUpdateCalculated = DateTime.Now; 
     _sampleSize = sampleSize; 
     _valueDelay = valueDelay; 
    } 

    public void NewFile() 
    { 
     _previousProgress = 0; 
    } 

    public void SetProgress(long bytesReceived, long totalBytesToReceive) 
    { 
     _totalFileSize = totalBytesToReceive; 

     long diff = bytesReceived - _previousProgress; 
     if (diff <= 0) 
      return; 

     _previousProgress = bytesReceived; 

     _changes.Enqueue(new Tuple<DateTime, long>(DateTime.Now, diff)); 
     while (_changes.Count > _sampleSize) 
      _changes.Dequeue(); 
    } 

    public double GetProgress() 
    { 
     return _previousProgress/(double) _totalFileSize; 
    } 

    public string GetProgressString() 
    { 
     return String.Format("{0:P0}", GetProgress()); 
    } 

    public string GetBytesPerSecondString() 
    { 
     double speed = GetBytesPerSecond(); 
     var prefix = new[] { "", "K", "M", "G"}; 

     int index = 0; 
     while (speed > 1024 && index < prefix.Length - 1) 
     { 
      speed /= 1024; 
      index++; 
     } 

     int intLen = ((int) speed).ToString().Length; 
     int decimals = 3 - intLen; 
     if (decimals < 0) 
      decimals = 0; 

     string format = String.Format("{{0:F{0}}}", decimals) + "{1}B/s"; 

     return String.Format(format, speed, prefix[index]); 
    } 

    public double GetBytesPerSecond() 
    { 
     if (DateTime.Now >= _lastUpdateCalculated + _valueDelay) 
     { 
      _lastUpdateCalculated = DateTime.Now; 
      _cachedSpeed = GetRateInternal(); 
     } 

     return _cachedSpeed; 
    } 

    private double GetRateInternal() 
    { 
     if (_changes.Count == 0) 
      return 0; 

     TimeSpan timespan = _changes.Last().Item1 - _changes.First().Item1; 
     long bytes = _changes.Sum(t => t.Item2); 

     double rate = bytes/timespan.TotalSeconds; 

     if (double.IsInfinity(rate) || double.IsNaN(rate)) 
      return 0; 

     return rate; 
    } 
} 

在下面的例子中,進度跟蹤器會給你最後50的平均下載速率接收的數據包,但只有每500毫秒(所以UI不會閃爍)。您可能需要稍微修改這些值才能在精確度和平滑度之間找到一個良好的平衡點。

//Somewhere in your constructor/initializer: 
tracker = new DownloadProgressTracker(50, TimeSpan.FromMilliseconds(500)); 

void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) 
{ 
    tracker.SetProgress(e.BytesReceived, e.TotalBytesToReceive); 
    pBarFileProgress.Value = tracker.GetProgress() * 100; 
    label1.Text = e.BytesReceived + "/" + e.TotalBytesToReceive; 
    label2.Text = tracker.GetBytesPerSecondString(); 
} 

請記住,你有之前或之後,每一個新的文件,以跟蹤復位:

tracker.NewFile(); 

如果你需要一些更大的文件有,我已經對此進行測試發現了一些here

+0

我收到錯誤的線路跟蹤器= new DownloadProgressTracker.DownloadProgress(e.TotalBytesToReceive,50,TimeSpan.FromMilliseconds(500));嚴重程度\t代碼\t說明\t'DownloadProgressTracker.DownloadProgress'不包含帶3個參數的構造函數 –

+0

只是爲了說清楚,DownloadProgressTracker.DownloadProgress是我創建的一個新類。我調用了新類DownloadProgressTracker,幫助器是DownloadProgress。 –

+0

@DanielHalfoni我剛剛意識到我複製了兩個不同版本的代碼。更新的代碼應該可以工作。 –

相關問題