The goal is to calculate and display on label4.Text the download speed while downloading.
private void Download()
{
using (var client = new WebClient())
{
client.DownloadFileCompleted = (s, e) => label1.Text = "Download file completed.";
client.DownloadProgressChanged = (s, e) => progressBar1.Value = e.ProgressPercentage;
client.DownloadProgressChanged = (s, e) => label2.Text = FormatBytes(e.BytesReceived);
client.DownloadProgressChanged = (s, e) => label4.Text = e.
client.DownloadProgressChanged = (s, e) =>
{
label3.Text = "%" e.ProgressPercentage.ToString();
label3.Left = Math.Min(
(int)(progressBar1.Left e.ProgressPercentage / 100f * progressBar1.Width),
progressBar1.Width - label3.Width
);
};
client.DownloadFileAsync(new Uri("https://speed.hetzner.de/10GB.bin"), @"d:\10GB.bin");
}
}
At the line with the label4.Text I want to display the speed.
client.DownloadProgressChanged = (s, e) => label4.Text = e.
CodePudding user response:
As @AKX suggested, Stopwatch
class help you to calculate bytes per second receive while downloading file.
Create a field in class scope (example based on WPF Application):
public partial class MainWindow : Window
{
private readonly System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
}
When initializing WebClient
(as simplest way), create 2 handlers: for WebClient.DownloadProgressChanged
event and for WebClient.DownloadFileCompleted
event. Then before you call WebClient.DownloadFileAsync()
call stopwatch.Start()
to begin measuring time.
using (System.Net.WebClient wc = new System.Net.WebClient())
{
wc.DownloadProgressChanged = OnDownloadProgressChange;
wc.DownloadFileCompleted = OnDownloadFileComplete;
stopwatch.Start(); // Start the Stopwatch
wc.DownloadFileAsync(downloadLink, fileName); // Run file download asynchroniously
}
In DownloadProgressChanged
event handler you can combine DownloadProgressChangedEventArgs
's BytesReceived
property and Stopwatch
's Elapsed.TotalSeconds
property to get download speed:
private void OnDownloadProgressChange(object sender, System.Net.DownloadProgressChangedEventArgs e)
{
// Calculate progress values
string downloadSpeed = string.Format("{0} MB/s", (e.BytesReceived / 1024.0 / 1024.0 / stopwatch.Elapsed.TotalSeconds).ToString("0.00"));
}
I divide BytesReceived
twice by 1024 to get value in MB instead of Bytes, but you can choose as you wish. Also I format result value to 0.00
(to get "1.23 MB/s" for example).
You can also calculate and format other DownloadProgressChangedEventArgs
properties for you purposes if needed.
And finally, at WebClient.DownloadFileCompleted
event handler you should reset the Stopwatch
to stop it and reset its measured time for other new downloads:
private void OnDownloadFileComplete(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
stopwatch.Reset();
}
Complete version may look like this (MainWindow.cs
):
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private readonly System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
private void BtnDownloadFile_Click(object sender, RoutedEventArgs e)
{
Uri downloadLink = new Uri("https://speed.hetzner.de/100MB.bin");
string fileName = "H:\\100MB.bin";
btnDownloadFile.IsEnabled = false; // Disable to prevent multiple runs
using (System.Net.WebClient wc = new System.Net.WebClient())
{
wc.DownloadProgressChanged = OnDownloadProgressChange;
wc.DownloadFileCompleted = OnDownloadFileComplete;
stopwatch.Start();
wc.DownloadFileAsync(downloadLink, fileName);
}
}
private void OnDownloadProgressChange(object sender, System.Net.DownloadProgressChangedEventArgs e)
{
// Calculate progress values
string downloadProgress = e.ProgressPercentage "%";
string downloadSpeed = string.Format("{0} MB/s", (e.BytesReceived / 1024.0 / 1024.0 / stopwatch.Elapsed.TotalSeconds).ToString("0.00"));
string downloadedMBs = Math.Round(e.BytesReceived / 1024.0 / 1024.0) " MB";
string totalMBs = Math.Round(e.TotalBytesToReceive / 1024.0 / 1024.0) " MB";
// Format progress string
string progress = $"{downloadedMBs}/{totalMBs} ({downloadProgress}) @ {downloadSpeed}"; // 10 MB / 100 MB (10%) @ 1.23 MB/s
// Set values to contols
lblProgress.Content = progress;
progBar.Value = e.ProgressPercentage;
}
private void OnDownloadFileComplete(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
lblProgress.Content = "Download complete!";
stopwatch.Reset();
btnDownloadFile.IsEnabled = true; // Restore arailability of download button
}
}
XAML:
<Grid>
<StackPanel HorizontalAlignment="Stretch"
VerticalAlignment="Center">
<Label x:Name="lblProgress"
Content="Here would be progress text"
Margin="10,0,10,5"
HorizontalContentAlignment="Center"/>
<ProgressBar x:Name="progBar"
Height="20"
Margin="10,0,10,5" />
<Button x:Name="btnDownloadFile"
Content="Download file"
Width="175"
Height="32"
Click="BtnDownloadFile_Click"/>
</StackPanel>
</Grid>
How it would look: