I am attempting to have a progress bar's progress change as the WebClient
download progress changes. This code still downloads the file yet when I call startDownload()
the window freezes as it downloads the file. I would like for the user to be able to see the progress change as the splash screen loads. Is there any way to fix this so that the user can see the progress of progressBar2
change?
private void startDownload()
{
WebClient client = new WebClient();
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
client.DownloadFileAsync(new Uri("http://joshua-ferrara.com/luahelper/lua.syn"), @"C:\LUAHelper\Syntax Files\lua.syn");
}
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;
label2.Text = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
}
void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
label2.Text = "Completed";
}
UI Thread will be freezed when you click startDownload(). If you don't want get form freezed, you use startDownload() in another thread and make progress updating in cross-threaded. One way,
private void startDownload()
{
Thread thread = new Thread(() => {
WebClient client = new WebClient();
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
client.DownloadFileAsync(new Uri("http://joshua-ferrara.com/luahelper/lua.syn"), @"C:\LUAHelper\Syntax Files\lua.syn");
});
thread.Start();
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
this.BeginInvoke((MethodInvoker) delegate {
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = bytesIn / totalBytes * 100;
label2.Text = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
});
}
void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
this.BeginInvoke((MethodInvoker) delegate {
label2.Text = "Completed";
});
}
Read more multi-threading in Google like this http://msdn.microsoft.com/en-us/library/ms951089.aspx
-Fixed missing close ); to the bgThread declaration
You should call startDownload()
from the UI thread. The whole idea of WebClient.DownloadFileAsync()
is that it will spawn a worker thread for you automatically without blocking the calling thread. In startDownload()
, you specified callbacks that modify controls which I assume were created by the UI thread. Thus if you call startDownload()
from a background thread it will cause problems, because a thread can only modify UI elements it created.
The way it is supposed to work is you call startDownload()
from the UI thread, startDownload()
as you defined it sets up event call backs that are handled by the UI thread. It then starts the download asynchronously and returns immediately. The UI thread will be notified when the progress changes and the code responsible for updating the progress bar control will execute on the UI thread, and there shouldn't be any problems.
public class ProgressEventArgsEx
{
public int Percentage { get; set; }
public string Text { get; set; }
}
public async static Task<string> DownloadStraingAsyncronous(string url, IProgress<ProgressEventArgsEx> progress)
{
WebClient c = new WebClient();
byte[] buffer = new byte[1024];
var bytes = 0;
var all = String.Empty;
using (var stream = await c.OpenReadTaskAsync(url))
{
int total = -1;
Int32.TryParse(c.ResponseHeaders[HttpRequestHeader.ContentLength], out total);
for (; ; )
{
int len = await stream.ReadAsync(buffer, 0, buffer.Length);
if (len == 0)
break;
string text = c.Encoding.GetString(buffer, 0, len);
bytes += len;
all += text;
if (progress != null)
{
var args = new ProgressEventArgsEx();
args.Percentage = (total <= 0 ? 0 : (100 * bytes) / total);
progress.Report(args);
}
}
}
return all;
}
// Sample
private async void Bttn_Click(object sender, RoutedEventArgs e)
{
//construct Progress<T>, passing ReportProgress as the Action<T>
var progressIndicator = new Progress<ProgressEventArgsEx>(ReportProgress);
await TaskLoader.DownloadStraingAsyncronous(tbx.Text, progressIndicator);
}
private void ReportProgress(ProgressEventArgsEx args)
{
this.statusText.Text = args.Text + " " + args.Percentage;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With