backgroundwork and progress

A

auldh

am having a hard time wrapping my head around "backgroundworker" class and
updates to the window form that calls it.

i have some questions about how to update windows form controls.
i have multiple labels and i'm using a text box for status updates.
the labels change when a task completes.
the text box report what task is running.

so
1) when i call _ProgressChange i need that function to passed the label i
want updating and what message?
2) does _ProgressChange know how to update the label and text box or do i
have to defind other parameters to link the windows form control to the
_ProgressChange.
3) if i have many functions that start after each other and they give status
do i need a different "backgroundworker" for each function? or can they be
tied to one thread? (each function relays on the first one to finish before
the next one starts).


does anyone or has anyone come across a good complex sample of a
"backgroundwork" class with multiple _ProgressChange?
 
A

Andy

am having a hard time wrapping my head around "backgroundworker" class and
updates to the window form that calls it.

i have some questions about how to update windows form controls.
i have multiple labels and i'm using a text box for status updates.
the labels change when a task completes.
the text box report what task is running.

so
1) when i call _ProgressChange i need that function to passed the label i
want updating and what message?
2) does _ProgressChange know how to update the label and text box or do i
have to defind other parameters to link the windows form control to the
_ProgressChange.
3) if i have many functions that start after each other and they give status
do i need a different "backgroundworker" for each function? or can they be
tied to one thread? (each function relays on the first one to finish before
the next one starts).

does anyone or has anyone come across a good complex sample of a
"backgroundwork" class with multiple _ProgressChange?

You don't call your objectName_ProductChanged method. You call the
instance method ReportProgress on the background worker. That method
handles doing the thread switching and raising the _ProgressChanged
event on the proper thread.

So you would have:

private void bworker1_DoWork( object sender, DoWorkEventArgs e ) {
BackgroundWorker worker;

worker = (BackgroundWorker)sender;

for ( int i = 0 ; i < 10 ; i += 1 ) {
worker.ReportProgress( i, null );
}
}

private void bworker1_ProgressChanged( object sender,
ProgressChangedEventArgs e ) {
myProgressBar.Value = e.ProgressPercentage * 10;
}

DoWork occurs on the background thread; all other event handlers for
the BackgroundWorker occur on the UI thread.

HTH
Andy
 
C

Cor Ligthert[MVP]

Auldh,
but what about the questions i have?

Then you should in my idea first give an explanation what your problem is.

Telling that you call _ProgressChange can be very misleading as Andy assumed
that you were invoking the event from the background class, however in fact
there is in my idea not direct a reason to expect thAT, it can be everything
else.

Cor
 
J

Joachim Van den Bogaert

3) Seems like the operations you want to do in a separate thread are
dependent on one another. Putting heavy work on a separate thread is
ok to make sure your gui remains responsive. Make sure though, that
putting each operation in a separate thread is worth the overhead.
This is a good article:

http://www.yoda.arachsys.com/csharp/threads/

1 + 2 + does anyone or has anyone come across a good complex sample of
a
"backgroundwork" class with multiple _ProgressChange?

You might consider using the Observer pattern

http://en.wikipedia.org/wiki/Observer_pattern

and implement it using thread safe operations:

http://blog.devstone.com/aaron/archive/2005/11/21/1351.aspx

Regards,
Joachim
 
A

auldh

thanks. i'm sorry if i'm not using the right terms.

i will try to be clearer as i try to explain my issues. i'm suppling a mock
up of my program. i put ":" in place where there is code not related to my
BackgroundWorker.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.VisualBasic;
using System.Threading;


namespace CallFlow
{

public partial class fCallFlow : Form
{

public fCallFlow()
{
InitializeComponent();
InitializeBackgroudWorker();
}
private void InitializeBackgroudWorker()
{
bgWorker.DoWork += new
System.ComponentModel.DoWorkEventHandler(this.bgWorker_DoWork);
//bgWorker.ProgressChanged += new
ProgressChangedEventHandler(bgWorker_ProgressChanged);
bgWorker.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
}
private bool parseuserlog(string filename, string sfilename)
{
:
:
:
//do some work
// update the windows form giving status to the user
tbStatus.Text = "Reading the input file. Creating temp
files.\r\n";
:
//the code for heavy processing
:
:
}//private bool parseuserlog(string filename)

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
runProgram((string)e.Argument, worker, e);
}//private void bgWorker_DoWork(object sender, DoWorkEventArgs e)

private void bgWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
MessageBox.Show("Canceled");
this.bgWorker.CancelAsync();
}
else
{
MessageBox.Show("Done");
}
}//private void bgWorker_RunWorkerCompleted(oject sender,
RunWorkerCompletedEventArgs e)


private void bgWorker_ProgressChangeed(object sender,
ProgressChangedEventArgs e)
{
//e.UserState
//ProgressChangedEventArgs.UserState property
}

private void runProgram(string filename, BackgroundWorker worker,
DoWorkEventArgs e)
{
:
//check the windows form to see if a user option is set
if (cbTraces.Checked == true)
bTrace = true;
:
//get the file name to append to the output files.
sfilename = fileChoice.SafeFileName.Substring(0,
fileChoice.SafeFileName.IndexOf("."));
if (worker.CancellationPending)
{
e.Cancel = true;
}
//call the code that does the heavy process
if (!parseuserlog(filename, sfilename))
{
MessageBox.Show("Error in parseuserlog function.");
Application.Exit();
}
:
//provide a status to the window form
tbStatus.Text += "Starting to process the PHHONEMAIL script
data.\r\n";
tbStatus.Refresh();
if (worker.CancellationPending)
{
e.Cancel = true;
}
//code to call another heavy task
if (!parsephonemaildata2(sfilename))
MessageBox.Show("Error");
:
//provide a status to the window form
tbStatus.Text += "Starting to process the Vogue script data.\r\n";
tbStatus.Refresh();

//code to call another heavy task
if (!parsevoguedata2(sfilename))
{
MessageBox.Show("Error in parsevoguedata function.");
Application.Exit();
}
//provide status to the window form
tbStatus.Text += "Starting to process data AVERAGES.\r\n";
tbStatus.Refresh();
if (worker.CancellationPending)
{
e.Cancel = true;
}
//code to call another heavy task
getAverages(sfilename);

}//private void runProgram(string useless, BackgroundWorker worker,
DoWorkEventArgs e)

private void bProcess_Click(object sender, EventArgs e)
{
:
:
//code that starts when the user selects a window form button
:
//start the background thread
bgWorker.RunWorkerAsync(filename);
:
}//private void bProcess_Click(object sender, EventArgs e)

private bool parsephonemaildata2(string sfilename)
{
:
//heavy code task with no status to the window form
:
return (true);
}//private bool parsephonemaildata2()

private bool parsevoguedata2(string sfilename)
{
:
//code for heavy task.
//status to update windows form
tbStatus.Text += "Number of lines ran in VOGUE script: " +
lSessionID.ToString() + "\r\n";
:
return (true);
}//private bool parsevoguedata2()

private void fCallFlow_Load(object sender, EventArgs e)
{
tbVersion.Text = "Version 2.2";
}//private long convertsession(string sSession)

private void bCancel_Click(object sender, EventArgs e)
{
Application.Exit();
}

}//public partial class fCallFlow : Form
}//namespace CallFlow

the windows form "command" button calls "private void bProcess_click(object
sender, EventArgs e)" which when invoked calls the function "private void
runProgram( string useless, BackgroundWorker worker, DoWorkEventArgs e)".
this inturns fires off the worker thread that calls 3 heavy process
functions.

one such function "private bool parseuser(string filename, string
sfilename)" does a heavy number crunching task and has to give an update to
the windows form not to a progress bar but to TextBox which i want to give
verbal updates.

the first issue i have is that i'm not sure if the "worker" object can be
passed down to this function? if so what is the method for this?

i guess if i can do that i can figure it out for the other functions called
by the "runProgram" function that controls the thread. (i'm sorry if still
get the terms wrong).

the sample i found talk about simple process to the progress bar and only 1
level. they don't outline how to update labels, textboxes, and statusbars.

thanks for any help.
 
A

auldh

Peter can you expand on your comment:
Everywhere that you have code to update status (e.g. >> tbStatus.Text +=
"Starting to process the PHHONEMAIL script data.\r\n" <<), you need to
replace that with a call to Invoke() that does the same thing, and get rid
of those calls to Refresh().

i can not see the forest through the trees. i can not find a good sample of
how to setup the Invoke method within a BackgroundWorker. seems samples use
the "progressbar" as their method of update.

so finding samples on updating labels, textbox and statusbar is difficult.

do i use "Delegate" and "InvokeRequired" in this operation?



Peter Duniho said:
[...]
the first issue i have is that i'm not sure if the "worker" object can be
passed down to this function? if so what is the method for this?

Of course it can. Just as you pass it to your runProgram() method, your
runProgram() method can pass it to subsequent methods that method calls.

Everywhere that you have code to update status (e.g. >> tbStatus.Text +=
"Starting to process the PHHONEMAIL script data.\r\n" <<), you need to
replace that with a call to Invoke() that does the same thing, and get rid
of those calls to Refresh().

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top