Windows Develop Bookmark and Share   
 index > Windows Forms General > How to use an event an another class to report progress in Main thread using BackgroundWorker.
 

How to use an event an another class to report progress in Main thread using BackgroundWorker.

Hello All,

I have a question regarding threading. Basically if there is a way to use BackgroundWorker here, or if I should roll out my own component.

I have two classes: FindFilesClass, and SaveFilesClass.
FindFilesClass - Using recursion it finds files that match certain criteria. It fires an event for each file found.
SaveFilesClass - Listens for this event and saves the file to a table in a DB.

Here is a snippet of both classes.

FindFilesClass
Code Snippet

public delegate void FileFoundHandler(object sender, FileFoundEventArgs e);
public event FileFoundHandler FileFoundEvent;

FileFoundEventArgs fileFoundEventArgs = new FileFoundEventArgs(fi);
if (FileFoundEvent != null)
{
FileFoundEvent(this, fileFoundEventArgs);
}

public class FileFoundEventArgs : EventArgs
{
private FileInfo _fileFound;

public FileFoundEventArgs(FileInfo fileFound)
{
_fileFound = fileFound;
}
public FileInfo FileFound
{
get { return _fileFound; }
}
}


SaveFilesClass
Code Snippet

public delegate void FileSavedHandler(object sender, FileSavedEventArgs e);
public event FileSavedHandler FileSavedEvent;

...

faf = new FindAudioFiles();
faf.FileFoundEvent += new FindAudioFiles.FileFoundHandler(this.OnFileFound);
faf.Start(path);

...

private void OnFileFound(object sender, FileFoundEventArgs e)
{
FileSavedEventArgs fileSavedEventArgs = new FileSavedEventArgs(e.FileFound);
if (FileSavedEvent != null)
{
FileSavedEvent(this, fileSavedEventArgs);
}
}

...

public class FileSavedEventArgs : EventArgs
{
private FileInfo _fileSaved;

public FileSavedEventArgs(FileInfo fileSaved)
{
_fileSaved = fileSaved;
}
public FileInfo FileSaved
{
get { return _fileSaved; }
}
}


How would I go about executing this in a thread?
My thought was to use BackgroundWorker. However, I want to have the files listed in the UI as they are saved (progress change event?). Since I register my own event I have stumbled a little on how I hook it up to the progress event of BackgroundWorker

In other words in DoWork I would call SaveFilesClass.Start() which begins the process. But how would I use my event in BackgrounWorker?

Or would I have to subclass BackgroundWorker? If so, could anyone point me to an example of this?

Thank you for any help or insight you can provide.

Anthony
obscured  Saturday, March 29, 2008 7:52 PM

Since the ProgressChanged event takes an integer and an object, you can pass an object to it and do whatever you want on the UI thread.

JohnWein  Sunday, March 30, 2008 8:43 AM

Hi obscured,

The following is my example and here’s a description of the execution sequence of the program:

· BackgourndWorker.RunWorkAsync() // in the Form1 Class

· BackgroundWorker.DoEvent()// in the Form1 Class

· FileFinder.BeginFindFiles()// in the FileFinder class

Send events

· FileSaver.OnFildFound()// in the FileSaver class

· BackgroudWorker.ReportProgress() // in the FileSaver class

· BackgourdWorker.ProgressChanged() // in the Form1 Class

Display file names in textBox1

Code Snippet

public partial class Form1 : Form

{

private FileFinder fileFinder;

private FileSaver fileSaver;

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

// initialize the fileFinder and fileSaver

fileFinder = new FileFinder();

fileSaver = new FileSaver(backgroundWorker1);

// hook up the event handler

fileFinder.FileFoundEvent += new FileFinder.FileFoundHandler(fileSaver.OnFileFound);

// initialize the Backgroundworker

backgroundWorker1.WorkerReportsProgress = true;

backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);

backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

}

void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)

{

textBox1.Text += "FileName: " + e.UserState.ToString() + "\r\n";

}

void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

{

fileFinder.BeginFindFiles();

}

private void startBackgroundWorkerButton_Click(object sender, EventArgs e)

{

backgroundWorker1.RunWorkerAsync();

}

}

To be continued...

Jacob Sui - MSFT  Thursday, April 03, 2008 4:48 AM
Rudedog2  Saturday, March 29, 2008 7:57 PM
Thanks for the reply. I did take a look at this sample which got me thinking about using BackgroundWorker. And it works great if you have one class and not registering your own events. Maybe I am just missing something, but I can not figure out how to show each file saved using backgroundworker's ProgressChangedEventArgs.

My thought is...

1. Call BgW DoWork to start the process.
2. Hook up BgW's progress reporting to my event to show each file saved (i.e. I want the files to show up in the UI as they are saved in some type of control)
3. Use the rest of BgW to handle cancel and completed events.

It is step 2 that I am not sure of. Seems to me I should be able to be a "listener" of the event and post the current file saved to the UI through BgW progress change method.

Not sure if this clears things up.

Thank you once again,
Anthony
obscured  Saturday, March 29, 2008 9:12 PM

Since the ProgressChanged event takes an integer and an object, you can pass an object to it and do whatever you want on the UI thread.

JohnWein  Sunday, March 30, 2008 8:43 AM

Hi obscured,

The following is my example and here’s a description of the execution sequence of the program:

· BackgourndWorker.RunWorkAsync() // in the Form1 Class

· BackgroundWorker.DoEvent()// in the Form1 Class

· FileFinder.BeginFindFiles()// in the FileFinder class

Send events

· FileSaver.OnFildFound()// in the FileSaver class

· BackgroudWorker.ReportProgress() // in the FileSaver class

· BackgourdWorker.ProgressChanged() // in the Form1 Class

Display file names in textBox1

Code Snippet

public partial class Form1 : Form

{

private FileFinder fileFinder;

private FileSaver fileSaver;

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

// initialize the fileFinder and fileSaver

fileFinder = new FileFinder();

fileSaver = new FileSaver(backgroundWorker1);

// hook up the event handler

fileFinder.FileFoundEvent += new FileFinder.FileFoundHandler(fileSaver.OnFileFound);

// initialize the Backgroundworker

backgroundWorker1.WorkerReportsProgress = true;

backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);

backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

}

void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)

{

textBox1.Text += "FileName: " + e.UserState.ToString() + "\r\n";

}

void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

{

fileFinder.BeginFindFiles();

}

private void startBackgroundWorkerButton_Click(object sender, EventArgs e)

{

backgroundWorker1.RunWorkerAsync();

}

}

To be continued...

Jacob Sui - MSFT  Thursday, April 03, 2008 4:48 AM

Code Snippet

public class FileFoundEventArgs: EventArgs

{

private String m_fileName;

public String FileName

{

get

{

return m_fileName;

}

set

{

m_fileName = value;

}

}

public FileFoundEventArgs(String fileName)

{

m_fileName = fileName;

}

}

Code Snippet

public class FileFinder

{

public delegate void FileFoundHandler(object sender, FileFoundEventArgs e);

public event FileFoundHandler FileFoundEvent;

public void BeginFindFiles()

{

// Ten different files are found. File names are passed by FileFoundEventArgs

for (int i = 0; i < 10; i++)

{

FileFoundEvent(this, new FileFoundEventArgs("C:\\sample" + i.ToString() + ".txt"));

}

}

}

Code Snippet

public class FileSaver

{

private BackgroundWorker m_backgroundWorker;

private TextBox m_textBox;

private int precentage = 0;

public FileSaver(BackgroundWorker backgroundWorkerReference, TextBox textBoxReference)

{

this.m_backgroundWorker = backgroundWorkerReference;

this.m_textBox = textBoxReference;

}

public void OnFileFound(object sender, FileFoundEventArgs e)

{

m_backgroundWorker.ReportProgress(precentage, e.FileName);

precentage += 10;

//Attention: Change UI directly rather than using backgroundWorker.ReportProgress()

//m_textBox.Text += "FileName: " + e.FileName + "\r\n";

}

}

Best regards,

Jacob

Jacob Sui - MSFT  Thursday, April 03, 2008 4:50 AM
Thank you Jacob!

Sorry for th delay in responding, but this is what I was looking for. I actually ended up trying to implement the event-based async. pattern and surprisingly got it to work (well it seemed to work).

But this is a much less "code heavy" way of doing it. And I also wanted to see how it could be done with the BackgroundWorker. Something told me I might have to pass an instance of the BGW to the "file save" class.

Well now I am off to code. Thank you once again.

obscured  Saturday, April 05, 2008 11:46 AM

You can use google to search for other answers

Custom Search

More Threads

• Scrollbar moved to display left,top edge of usercontrol when usercontrol too wide
• How to develope .exe for winPE???
• Question on Modifying Settings.Designer.cs
• Bug?? Creating window
• Create word file in C#
• DoDragDrop() problem with FileDrop
• making Que threadsafe
• Button click with API ?
• What control is used in here?
• Exposing a button from a user control as the cancel button