Hi,
I've got a windows application that references a class library -
in my class library i have a method that returns a large collection.
on the windows form, i have a button, that calls the method.... the method takes about a minute or so to do what it needs to do (its a large operation)
when the button is pressed, the UI locks up - how can i make this happen on a different thread, and also, is it possible to add a progress bar to show how far along the operation is?
regards,
alex
Sunny ChenPosted Jul 5, 2008, 11:50 PM
In your form:
private void button1_click(object sender, System.EventArgs e)
{
ThreadStart threadStart = new ThreadStart(DoWork);
Thread thread = new Thread(threadStart);
thread.Start();
}
private void DoWork()
{
// ... Do your work here.
}
For the way of how to terminate the thread, please refer to the link: http://www.sunnychen.org/2008/05/23/CAndWinFormsApplicationsTerminateYourThread.aspx
Hope this helps.
Posted Jul 4, 2008, 5:58 PM
private void fileWorker_DoWork(object sender, DoWorkEventArgs e)
{
int totalProgress = 0;
int totalLines = 0;
List<string> data = new List<string>();
//If there are lines in the file to read...
totalLines = GetTotalLinesInFile("myfile.txt");
if (totalLines > 0)
{
// Just some file reading... This could be any sort of work really.
using (StreamReader reader = new StreamReader(File.Open("myfile.txt", FileMode.OpenOrCreate)))
{
while (!reader.EndOfStream)
{
data.Add(reader.ReadLine());
// After some work completes, update the total progress...
totalProgress++;
// Dividing this way will give you a decimal value, but you need an integer
// so multiply the decimal value by 100 to get say... 20 instead of 0.2 which
// when implicitly cast to an integer will round to 0 and do you no good.
fileWorker.ReportProgress((totalProgress / totalLines) * 100);
}
}
}
//When the read completes, you can (but don't have to) assign a result value object.
e.Result = data;
}
private int GetTotalLinesInFile(string filePath)
{
// There will probably be better ways to get a line count
// in a file. But I use this one often.
int lineCount = 0;
using (StreamReader reader = new StreamReader(File.Open(filePath, FileMode.OpenOrCreate)))
{
while (!reader.EndOfStream)
{
// Read the line, but dont do anything with it.
reader.ReadLine();
lineCount++;
}
}
return lineCount;
}
private void fileWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Update the progress bar
MyProgressBar.Value = e.ProgressPercentage;
}
private void fileWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// After the work completes, this event handler will be called
// and if you passed a result back, you can use it here.
List<string> data = (List<string>)e.Result;
// For instance, populate a list box
MyListBox.Items.AddRange(data.ToArray());
}
This worked ok for me for files up to 1 MB, but any larger and your going to need a more efficient method such as buffering and blocking. Or you could use the thread instance if you wanted more precise control over what was happening or if the BackgroundWorker wasnt sufficient enough. But keep in mind that when you use a Thread object, you must use a delegate to update user interface controls for thread safety.