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;
}
I believe this article will lead you in the right direction http://www.dreamincode.net/forums/topic/115491-download-file-asynchronously-with-progressbar/ .
And in this MSDN Article http://msdn.microsoft.com/en-us/library/ms229675.aspx discusses how "The file is downloaded on the BackgroundWorker component's worker thread, which runs the DoWork event handler. This thread starts when your code calls the RunWorkerAsync method."
Related
Before i tried to check if progressBar2 that show overall download progress is at 100% but it's not really working. Is there another way more sure way to check it ?
private void btnDownload_Click(object sender, EventArgs e)
{
//urll.Add("http://download.thinkbroadband.com/1GB.zip");
btnDownload.Enabled = false;
label7.Text = "Downloading...";
getTotalBytes(countryList);
CreateCountryDateTimeDirectories(newList);
downloadFile(newList);
}
private Queue<string> _downloadUrls = new Queue<string>();
private async void downloadFile(IEnumerable<string> urls)
{
foreach (var url in urls)
{
_downloadUrls.Enqueue(url);
}
await DownloadFile();
}
private async Task DownloadFile()
{
if (_downloadUrls.Any())
{
WebClient client = new WebClient();
client.DownloadProgressChanged += ProgressChanged;
client.DownloadFileCompleted += Completed;
var url = _downloadUrls.Dequeue();
sw = Stopwatch.StartNew();
if (url.Contains("true"))
{
await client.DownloadFileTaskAsync(new Uri(url), countriesMainPath + "\\" + currentDownloadCountry + "\\" + count + "Infrared.jpg");
}
else
{
await client.DownloadFileTaskAsync(new Uri(url), countriesMainPath + "\\" + currentDownloadCountry + "\\" + count + "Invisible.jpg");
}
return;
}
}
double percentageTotalDownload = 0;
double totalBytesDownloaded = 0;
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
// Calculate download speed and output it to labelSpeed.
label3.Text = string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00"));
// Update the progressbar percentage only when the value is not the same.
double bytesInCurrentDownload = (double)e.BytesReceived;
double totalBytesCurrentDownload = double.Parse(e.TotalBytesToReceive.ToString());
double percentageCurrentDownload = bytesInCurrentDownload / totalBytesCurrentDownload * 100;
ProgressBar1.Value = int.Parse(Math.Truncate(percentageCurrentDownload).ToString());//e.ProgressPercentage;
// Show the percentage on our label.
Label4.Text = e.ProgressPercentage.ToString() + "%";
// Update the label with how much data have been downloaded so far and the total size of the file we are currently downloading
label10.Text = string.Format("{0} MB's / {1} MB's",
(e.BytesReceived / 1024d / 1024d).ToString("0.00"),
(e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"));
//Let's update ProgressBar2
totalBytesDownloaded = e.BytesReceived + bytesFromCompletedFiles;
percentageTotalDownload = totalBytesDownloaded / totalBytesToDownload * 100;
progressBar2.Value = (int)percentageTotalDownload;
label6.Text = progressBar2.Value.ToString() + "%";
}
long bytesFromCompletedFiles = 0;
// The event that will trigger when the WebClient is completed
private async void Completed(object sender, AsyncCompletedEventArgs e)
{
await DownloadFile();
}
For example if i have 100 urls and it's start downloading then i want to know in the completed event when all the files downloaded and not only one each time.
You can keep track of how many downloads have been completed in an counter variable. Because of the multiple threads that can access that counter, use the Interlocked class to manipulate that counter.
This are the changes needed in your code:
private int urlCount = 0; // keep track of how many urls are processed
private async void downloadFile(IEnumerable<string> urls)
{
urlCount = 0;
foreach (var url in urls)
{
_downloadUrls.Enqueue(url);
urlCount++;
}
// urlCount is now set
await DownloadFile();
}
And here is the handling of the counter and the check if we are done
private async void Completed(object sender, AsyncCompletedEventArgs e)
{
// urlCount will be decremented
// cnt will get its value
var cnt = System.Threading.Interlocked.Decrement(ref urlCount);
if (cnt > 0) {
await DownloadFile();
}
else
{
// call here what ever you want to happen when everything is
// downloaded
"Done".Dump();
}
}
I haven't understood it very well, but what you are trying to accomplish is that your progress bar is showing progress of download all files and not one file then reset then another file that reset.
If that is the case, then why you do not try foreach file get size and sum it to totalBytesToDownload and then use it in progress bar
So
foreach(string url in urll)
{
//get url file size
totalBytesToDownload = totalBytesToDownload + urlSizeYouGot;
}
Here is some code that I use to download a file and then calculate the time remaining time and kbps. It will then post those results on the form by updating a text box and it has a progress bar. The problem I am having is the UI is freezing and I am thinking it might be how I am using the stopwatch but not sure. Anyone have any input?
/// Downloads the file.
private void Download_Begin()
{
web_client = new System.Net.WebClient();
web_client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Download_Progress);
web_client.DownloadFileCompleted += new AsyncCompletedEventHandler(Download_Complete);
stop_watch = new System.Diagnostics.Stopwatch();
stop_watch.Start();
try
{
if (Program.Current_Download == "Install_Client.exe")
{
web_client.DownloadFileAsync(new Uri("http://www.website.com/Client/Install_Client.exe"), #"C:\Downloads\Install_Client.exe");
}
else
{
web_client.DownloadFileAsync(new Uri((string.Format("http://www.website.com/{0}", Program.Current_Download))), (string.Format(#"C:\Downloads\{0}", Program.Current_Download)));
}
}
catch(Exception)
{
stop_watch.Stop();
}
Program.Downloading = true;
Download_Success = false;
}
/// -------------------
/// Tracks download progress.
private void Download_Progress(object sender, DownloadProgressChangedEventArgs e)
{
double bs = e.BytesReceived / stop_watch.Elapsed.TotalSeconds;
this.label_rate.Text = string.Format("{0} kb/s", (bs / 1024d).ToString("0.00"));
long bytes_remaining = e.TotalBytesToReceive - e.BytesReceived;
double time_remaining_in_seconds = bytes_remaining / bs;
var remaining_time = TimeSpan.FromSeconds(time_remaining_in_seconds);
string hours = remaining_time.Hours.ToString("00");
if (remaining_time.Hours > 99)
{
hours = remaining_time.Hours.ToString("000");
}
this.time_remaining.Text = string.Format("{0}::{1}::{2} Remaining", hours, remaining_time.Minutes.ToString("00"), remaining_time.Seconds.ToString("00"));
progressBar1.Maximum = (int)e.TotalBytesToReceive / 100;
progressBar1.Value = (int)e.BytesReceived / 100;
if (e.ProgressPercentage == 100)
{
Download_Success = true;
}
}
/// -------------------------
The UI thread could be freezing for various reasons, despite the fact that you are calling the asynchronous download function. One way of preventing the UI to freeze would be to invoke the downloading of the file from different thread than the UI. For instance you can accomplish this with BackgroundWorker and safely modify form's controls via thread safe calls or in short wrapping the code executed in the non-UI thread with BeginInvoke() calls.
private void button1_Click(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += Worker_DoWork;
worker.RunWorkerAsync();
}
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
Download_Begin();
}
/// Downloads the file.
private void Download_Begin()
{
web_client = new System.Net.WebClient();
web_client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Download_Progress);
web_client.DownloadFileCompleted += new AsyncCompletedEventHandler(Download_Complete);
stop_watch = new System.Diagnostics.Stopwatch();
stop_watch.Start();
try
{
if (Program.Current_Download == "Install_Client.exe")
{
web_client.DownloadFileAsync(new Uri("http://www.website.com/Client/Install_Client.exe"), #"C:\Downloads\Install_Client.exe");
}
else
{
web_client.DownloadFileAsync(new Uri((string.Format("http://www.website.com/{0}", Program.Current_Download))), (string.Format(#"C:\Downloads\{0}", Program.Current_Download)));
}
}
catch (Exception)
{
stop_watch.Stop();
}
Program.Downloading = true;
Download_Success = false;
}
/// -------------------
/// Tracks download progress.
private void Download_Progress(object sender, DownloadProgressChangedEventArgs e)
{
this.BeginInvoke(new Action(() =>
{
double bs = e.BytesReceived / stop_watch.Elapsed.TotalSeconds;
this.label_rate.Text = string.Format("{0} kb/s", (bs / 1024d).ToString("0.00"));
long bytes_remaining = e.TotalBytesToReceive - e.BytesReceived;
double time_remaining_in_seconds = bytes_remaining / bs;
var remaining_time = TimeSpan.FromSeconds(time_remaining_in_seconds);
string hours = remaining_time.Hours.ToString("00");
if (remaining_time.Hours > 99)
{
hours = remaining_time.Hours.ToString("000");
}
this.time_remaining.Text = string.Format("{0}::{1}::{2} Remaining", hours, remaining_time.Minutes.ToString("00"), remaining_time.Seconds.ToString("00"));
progressBar1.Maximum = (int)e.TotalBytesToReceive / 100;
progressBar1.Value = (int)e.BytesReceived / 100;
if (e.ProgressPercentage == 100)
{
Download_Success = true;
}
}));
}
Some thoughts about your code:
No need to close stopwatch when exceptions happen, stopwatch does not do any work inside, it simply remember current time when you start stopwatch and calculate difference when you access elapsed time.
When you catch all exceptions, there is no need to provide Exception class (i.e. catch instead of catch(Exception)).
Mark download as completed only in DownloadFileCompleted event, not in DownloadProgressChanged, because ProgressPercentage can be 100 even when download is not completed yet.
When working with async code it is always better to initialize status variables (in your case Download_Success and Program.Downloading) before calling async method, not after.
Now about freezes. DownloadProgreesChanged can be fired very often by WebClient, so UI thread can be flooded by update messages. You need to split report progress and update UI code. UI should be updated in timed manner, for example, twice per second. Very rough code sample below:
// Put timer on your form, equivalent to:
// Update_Timer = new System.Windows.Forms.Timer();
// Update_Timer.Interval = 500;
// Update_Timer.Tick += Timer_Tick;
private void Download_Begin()
{
web_client = new System.Net.WebClient();
web_client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Download_Progress);
web_client.DownloadFileCompleted += new AsyncCompletedEventHandler(Download_Complete);
Program.Downloading = true;
Download_Success = false;
stop_watch = System.Diagnostics.Stopwatch.StartNew();
Update_Timer.Start();
web_client.DownloadFileAsync(new Uri("uri"), "path");
}
private int _Progress;
private void Download_Progress(object sender, DownloadProgressChangedEventArgs e)
{
_Progress = e.ProgressPercentage;
}
private void Download_Complete(object sender, AsyncCompletedEventArgs e)
{
Update_Timer.Stop();
Program.Downloading = false;
Download_Success = true;
}
private void Timer_Tick(object sender, EventArgs e)
{
// Your code to update remaining time and speed
// this.label_rate.Text = ...
// this.time_remaining.Text = ...
progressBar1.Value = _Progress;
}
I'm using a thread to run a calculation in the background of my program. I start the thread at the start of my program. If I press a button before the thread is finished it will open the statusBar and "openedStatus" is set to true.
This will show the threads current progress and after the thread has finished I would like to execute the last part of my code:
if (openedStatus)
{
sb.Close();
validateBeforeSave();
}
This part of the code will throw an exception though because you can't close the statusbar cross-thread.
Now the question is: How can I execute that last part of the code after the thread is finished?
private StatusBar sb = new StatusBar();
private void startVoorraadCalculationThread()
{
sb.setMaxProgress(data.getProducten().getProductenCopy().Count);
Thread thread = new Thread(new ThreadStart(this.run));
thread.Start();
while (!thread.IsAlive) ;
}
private void run()
{
for (int i = 0; i < data.getProducten().getProductenCopy().Count; i++ )
{
sb.setProgress(i);
sb.setStatus("Calculating Voorraad: " + (i+1) + "/" + data.getProducten().getProductenCopy().Count);
data.getProducten().getProductenCopy()[i].getTotaalVoorraad(data.getMaten());
}
if (openedStatus)
{
sb.Close();
validateBeforeSave();
}
calculationFinished = true;
}
Using a backgroundWorker fixed my problem:
private void startVoorraadCalculationThread()
{
sb.setMaxProgress(data.getProducten().getProductenCopy().Count);
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync();
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < data.getProducten().getProductenCopy().Count; i++)
{
sb.setProgress(i);
sb.setStatus("Calculating Voorraad: " + (i + 1) + "/" + data.getProducten().getProductenCopy().Count);
data.getProducten().getProductenCopy()[i].getTotaalVoorraad(data.getMaten());
}
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (openedStatus)
{
sb.Close();
validateBeforeSave();
}
calculationFinished = true;
}
I'm trying to show a form that displays a label like "Updating, this window will close once update has finished" to download a few images files. I put this on my form's shown.
private void frmExtraUpdater_Shown(object sender, EventArgs e)
{
for (int i = 1; i < 8; i++)
{
string _EmoticonURL = String.Format("https://dl.dropboxusercontent.com/u/110636189/MapleEmoticons/f{0}.bmp", i);
WebRequest requestPic = WebRequest.Create(_EmoticonURL);
WebResponse responsePic = requestPic.GetResponse();
Image webImage = Image.FromStream(responsePic.GetResponseStream()); // Error
webImage.Save(Application.StartupPath + #"\Images\f" + i + ".bmp");
}
}
However.. once the form is shown, the label doesn't even show because it doesn't load it (It insantly downloades the images. I want it to show the label and only then start the download).
The other problem is that it throws "A generic error occurred in GDI+." on the webImgae.Save part for some reason.
Why's that?
Oh and.. if the folder "Images" does not exist, will it automatically create it?
Thanks!
Here is Jon Skeet suggestion:
System.Net.WebClient webClient = new System.Net.WebClient();
webClient.DownloadFile(String.Format("https://dl.dropboxusercontent.com/u/110636189/MapleEmoticons/f{0}.bmp", i), Application.StartupPath + #"\Images\f" + i + ".bmp");
Use a background worker to update any UI components
BackgroundWorker backTask = new BackgroundWorker();
public frmExtraUpdater()
{
backTask.DoWork += backTask_DoWork;
backTask.RunWorkerCompleted += backTask_RunWorkerCompleted;
}
private void frmExtraUpdater_Shown(object sender, EventArgs e)
{
yourLabel.Text = "Downloading";
backTask.RunWorkerAsync();
}
void backTask_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i < 8; i++)
{
System.Net.WebClient webClient = new System.Net.WebClient();
webClient.DownloadFile(String.Format("https://dl.dropboxusercontent.com/u/110636189/MapleEmoticons/f{0}.bmp", i), Application.StartupPath + #"\Images\f" + i + ".bmp");
backTask.ReportProgress(i * (100 / 8), String.Format("https://dl.dropboxusercontent.com/u/110636189/MapleEmoticons/f{0}.bmp", i));
}
}
void backTask_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
yourLabel.Text = "Downloading" + e.UserState.ToString();
}
void backTask_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.Close();
}
You should use an async method, with webrequest async api (if you work with .net 4.5 or sup) or download your images in a background thread to avoid ui thread blocking.
You can try that:
private void frmExtraUpdater_Shown(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (o, d) =>
{
saveImages();
};
worker.RunWorkerCompleted += (o, f) =>
{
this.Close();
};
worker.RunWorkerAsync();
}
private void saveImages()
{
for (int i = 1; i < 8; i++)
{
string _EmoticonURL = String.Format("https://dl.dropboxusercontent.com/u/110636189/MapleEmoticons/f{0}.bmp", i);
WebRequest requestPic = WebRequest.Create(_EmoticonURL);
WebResponse responsePic = requestPic.GetResponse();
Image webImage = Image.FromStream(responsePic.GetResponseStream()); // Error
webImage.Save(Application.StartupPath + #"\Images\f" + i + ".bmp");
}
}
The following is my background worker thread
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Thread t1 = new Thread(Thread1);
t1.Start();
Thread t2 = new Thread(Thread2);
t2.Start();
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
}
}
Thread1 code is as follows
static void Thread1()
{
int nofiles=0;
int returned = checkforfolderthread(1);
int startvalue = 0;
int stopvalue = 5000;
if (returned == 1)
{
nofiles = countfiles();
startvalue = startvalue + (nofiles - 1) * 1000;
stopvalue = stopvalue - startvalue;
}
repeat(startvalue, stopvalue,1,nofiles-1);
}
Function called from a thread is as follows
static void repeat(int ini, int fin, int threadno, int startadd)
{
int i, j;
for (j = ini; j < ini + fin; j += 1000)
{
StringBuilder sb = new StringBuilder();
for (i = j; i < j + 1000; i += 100)
{
WebClient wc = new WebClient();
string add = System.String.Format("http://www.colourlovers.com/api/colors/new?numResults=100&resultOffset={0}", i);
try
{
string tobeadded = wc.DownloadString(add);
sb.AppendLine();
sb.Append(tobeadded);
}
catch (Exception)
{
break;
}
}
string folderpath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string filename = System.String.Format("DownloadPalette\\Thread{0}\\color{1}.xml",threadno,startadd);
string location = Path.Combine(folderpath, filename);
File.WriteAllText(location, sb.ToString());
startadd = startadd + 1;
}
}
What I would want to do is continuously update a progressbar after each for i loop is completed.
But I cannot access the progressbar from this function running in the background thread.
Please Help me
You miss this method..
// Back on the 'UI' thread so we can update the progress bar
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// The progress percentage is a property of e
progressBar1.Value = e.ProgressPercentage;
}
According on this reference : BackgroundWorker and ProgressBar demo
You should use invoke, as described here: http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx
First create a method to update the progressbar(create it on the main thread GUI):
private void UpdateBar()
{
//your code to update
}
Then create a delegate and pass you method to it(this code is also for main thread GUI):
private delegate void UpdateProgressBarDelegate();
private UpdateProgressBarDelegate UpdateProgressBarDelegate_Object;
UpdateProgressBarDelegate_Object = new UpdateProgressBarDelegate(this.UpdateBar);
Now update it from another thread like this:
progressbar.Invoke(UpdateProgressBarDelegate_Object);
Here we are calling the delegate object which will call UpdateBar method on GUI thread with a safe thread call.
If you need to update more than just the progressbar value you could call a method and checking if an invoke is required. An invoke is required if you want to access a UI object from a separate thread.
private void updateProgress(object sender, int count, int total)
{
if (base.InvokeRequired)
{
base.Invoke(new ProcessCountHandler(this.updateProgress), new object[] { sender, count, total });
}
else if (count <= this.progressBar1.Maximum)
{
this.progressBar1.Value = count;
this.CompletedCount.Text = count.ToString("N0") + " of " + total.ToString("N0");
}
}