Calculating the progress percentage
I am using webclient to dowlnoad a file. I am calculating the progress percentage as below
I know the filesize (I read it from the database table) of the file going to be downloaded.
I am depending on the
BytesRecieved
property of WebClient to know the total bytes fetched during download.The algorithm I am using is
double dProgress = (e.BytesReceived / FileSize)*100);
to calculate the progress percentage.
However i am not getting correct progress percentage to update the progress bar.
Is there any method to calculate progress开发者_C百科 percentage?
Look at the following line:
double dProgress = (e.BytesReceived / FileSize)*100)
If both e.BytesReceived
and FileSize
are integers then you will always have 0 * 100 = 0
.
Make something like this:
double dProgress = ((double)e.BytesReceived / FileSize)*100.0
It is because /
does integer division when dividing two integers. But you don't want that. So you convert one of the variables to double
.
BytesReceived and FileSize most probably are integers so you need to calculate progress this way:
double dProgress = 100.0 * e.BytesReceived / FileSize;
If you are handling the DownloadProgressChanged
event when doing an asynchronous download, the event args already has a ProgressPercentage
on it, so there is no point in re-inventing it. A contrived example:
var client = new WebClient();
var reset = new ManualResetEvent(false);
client.DownloadProgressChanged += (s, e) => Console.WriteLine("{0} percent complete", e.ProgressPercentage);
client.DownloadFileCompleted += (s, e) => reset.Set();
client.DownloadFileAsync(new Uri("http://myfilepathhere.com"), "file.name");
//Block till download completes
reset.WaitOne();
The problem is that both numbers are integers. When you devide them, they become smaller than 1, so they round down to 0. Typecast them to make the result a float:
double dProgress = ((double)e.BytesReceived / FileSize)*100)
This is a very tricky problem with basic arithmetic and casting in C#.
Solution
First store the result of integer division in a double variable. And then type cast that to an integer.
int x = 5, y = 10, answer;
double ansDouble;
answer = (int)(x / y) * 100; //percentage calculation
Console.WriteLine("percentage={0}", answer);
//>output percentage=0
answer = (int)((double)x / y) * 100; //percentage calculation
Console.WriteLine("percentage={0}", answer);
//>output percentage=0
answer = (int)((double)x / (double)y) * 100; //percentage calculation
Console.WriteLine("x={0}", answer);
//>output percentage=0
answer = (int)(x/(double)y) * 100; //percentage calculation
Console.WriteLine("x={0}", answer);
//>output percentage=0
ansDouble = ((double)x / y) * 100;
answer = (int)ansDouble;
Console.WriteLine("percentage={0}", answer);
//>output percentage=50
Points to note
Turns out that x/y = 0, for any values of x and y as long as they are integers We can't solve this in one line by any casting combinations
Try this:
WebClient Client = new WebClient();
Client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
...
void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) {
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = bytesIn / totalBytes * 100;
int percente = int.Parse(Math.Truncate(percentage).ToString());
progressBar.Value = percente;
}
Or just using the ProgressPercentage
value.
void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) {
progressBar.Value = e.ProgressPercentage;
}
精彩评论