Background worker tasks sequentially?

S

sjoshi

I'm able to use the Bacground Worker class to execute task and pain the
UI. However I want to be able to execute n tasks in order, say n1, then
n2 if there were no errors during n1, n3 so on.

I'm wondering what would be the best way to do this , do I wait in a
do...while loop for each to finish and then start another ?

thanks
Sunit
 
N

Nicholas Paldino [.NET/C# MVP]

Sunit,

That's basically what you will have to do. It seems like you have three
tasks, but you want all three to run sequentially, just not on the UI
thread. You can still use the BackgroundWorker class for this, you just
have to do the first task with it, then the second, then the third, and so
on, and so on.

Hope this helps.
 
B

Brian Gideon

Sunit,

In addition to what Nicholas said there is an event on the
BackgroundWorker class that is raised when the task is complete. You
should be able to use that to your advantage.

Brian
 
S

sjoshi

Nicholas said:
Sunit,

That's basically what you will have to do. It seems like you have three
tasks, but you want all three to run sequentially, just not on the UI
thread. You can still use the BackgroundWorker class for this, you just
have to do the first task with it, then the second, then the third, and so
on, and so on.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

sjoshi said:
I'm able to use the Bacground Worker class to execute task and pain the
UI. However I want to be able to execute n tasks in order, say n1, then
n2 if there were no errors during n1, n3 so on.

I'm wondering what would be the best way to do this , do I wait in a
do...while loop for each to finish and then start another ?

thanks
Sunit
Ok thanks I need to run a background task for each row ina dset. So I
tried this:

foreach (DAO.DAODatabase.DatabaseRow backupEntry in
_srvBackupDSet.Database)
{
InitAndStartBackgroundWorker(backupEntry);
while (!_lastRunFinished)
{
Thread.Sleep(500);
}
if (!_lastRunOk)
break;
}
private void InitAndStartBackgroundWorker(DAO.DAODatabase.DatabaseRow
backupRow)
{
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;

//Set background worker
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged += new
ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

//Start Backup
worker.RunWorkerAsync(backupRow);
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
_lastRunFinished = false;
_backupMgr.PercentCompleted += new
PercentEventHandler(_backupMgr_PercentCompleted);
BackgroundWorker theWorker = sender as BackgroundWorker;
DoBackup((DAO.DAODatabase.DatabaseRow)e.Argument);
}

void worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
_lastRunOk = false ;
UpdateGridForError(e.Error);
}
else
_lastRunOk = true;
_lastRunFinished = true;
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//code to UpdateGrid progress bar
}

However now the UI freezes and the 1st job itself never completes; i.e
the run worker_RunWorkerCompleted event is never raised.

It works fine if I just pass a single row.

thanks
Sunit
 
N

Nicholas Paldino [.NET/C# MVP]

It looks like you are waiting on a loop until the processing is done.
You should be letting the events that the BackgroundThread fires tell you
when you are done instead of waiting for the variables to be set (which you
are doing the wrong way, since you are not locking access to them).


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

sjoshi said:
Sunit,

That's basically what you will have to do. It seems like you have
three
tasks, but you want all three to run sequentially, just not on the UI
thread. You can still use the BackgroundWorker class for this, you just
have to do the first task with it, then the second, then the third, and
so
on, and so on.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

sjoshi said:
I'm able to use the Bacground Worker class to execute task and pain the
UI. However I want to be able to execute n tasks in order, say n1, then
n2 if there were no errors during n1, n3 so on.

I'm wondering what would be the best way to do this , do I wait in a
do...while loop for each to finish and then start another ?

thanks
Sunit
Ok thanks I need to run a background task for each row ina dset. So I
tried this:

foreach (DAO.DAODatabase.DatabaseRow backupEntry in
_srvBackupDSet.Database)
{
InitAndStartBackgroundWorker(backupEntry);
while (!_lastRunFinished)
{
Thread.Sleep(500);
}
if (!_lastRunOk)
break;
}
private void InitAndStartBackgroundWorker(DAO.DAODatabase.DatabaseRow
backupRow)
{
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;

//Set background worker
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged += new
ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

//Start Backup
worker.RunWorkerAsync(backupRow);
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
_lastRunFinished = false;
_backupMgr.PercentCompleted += new
PercentEventHandler(_backupMgr_PercentCompleted);
BackgroundWorker theWorker = sender as BackgroundWorker;
DoBackup((DAO.DAODatabase.DatabaseRow)e.Argument);
}

void worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
_lastRunOk = false ;
UpdateGridForError(e.Error);
}
else
_lastRunOk = true;
_lastRunFinished = true;
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//code to UpdateGrid progress bar
}

However now the UI freezes and the 1st job itself never completes; i.e
the run worker_RunWorkerCompleted event is never raised.

It works fine if I just pass a single row.

thanks
Sunit
 
S

sjoshi

Nicholas said:
It looks like you are waiting on a loop until the processing is done.
You should be letting the events that the BackgroundThread fires tell you
when you are done instead of waiting for the variables to be set (which you
are doing the wrong way, since you are not locking access to them).


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

sjoshi said:
Sunit,

That's basically what you will have to do. It seems like you have
three
tasks, but you want all three to run sequentially, just not on the UI
thread. You can still use the BackgroundWorker class for this, you just
have to do the first task with it, then the second, then the third, and
so
on, and so on.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I'm able to use the Bacground Worker class to execute task and pain the
UI. However I want to be able to execute n tasks in order, say n1, then
n2 if there were no errors during n1, n3 so on.

I'm wondering what would be the best way to do this , do I wait in a
do...while loop for each to finish and then start another ?

thanks
Sunit
Ok thanks I need to run a background task for each row ina dset. So I
tried this:

foreach (DAO.DAODatabase.DatabaseRow backupEntry in
_srvBackupDSet.Database)
{
InitAndStartBackgroundWorker(backupEntry);
while (!_lastRunFinished)
{
Thread.Sleep(500);
}
if (!_lastRunOk)
break;
}
private void InitAndStartBackgroundWorker(DAO.DAODatabase.DatabaseRow
backupRow)
{
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;

//Set background worker
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged += new
ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

//Start Backup
worker.RunWorkerAsync(backupRow);
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
_lastRunFinished = false;
_backupMgr.PercentCompleted += new
PercentEventHandler(_backupMgr_PercentCompleted);
BackgroundWorker theWorker = sender as BackgroundWorker;
DoBackup((DAO.DAODatabase.DatabaseRow)e.Argument);
}

void worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
_lastRunOk = false ;
UpdateGridForError(e.Error);
}
else
_lastRunOk = true;
_lastRunFinished = true;
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//code to UpdateGrid progress bar
}

However now the UI freezes and the 1st job itself never completes; i.e
the run worker_RunWorkerCompleted event is never raised.

It works fine if I just pass a single row.

thanks
Sunit

Yes I forgot about the locking...will that be the reason for freeeze ?
I do set the variables in the RunWorkerCompleted event so that I can
know when to start another one and as such I can create a new
BackgroundWorker in the InitAndStart method. Is this the correct way to
start next task ?
Can you please let me know what I'm doing wrong here (pseudo code...)

thanks
Sunit
 
P

Peter Duniho

sjoshi said:
I'm able to use the Bacground Worker class to execute task and pain the
UI. However I want to be able to execute n tasks in order, say n1, then
n2 if there were no errors during n1, n3 so on.

I'm wondering what would be the best way to do this , do I wait in a
do...while loop for each to finish and then start another ?

If you want tasks processed sequentially, you need a queue of some sort.

One way to do this would be to take advantage of the suggestions offered so
far. You would add the tasks to the queue, and then use the event Brian
mentions to know when to start a new task thread.

Alternatively, you could just keep a single background thread running that
pulls tasks from the queue as long as the queue isn't empty. Once the queue
is empty, the background thread could wait on an EventWaitHandle that the
main thread would set any time it adds something to the queue.

In either approach, you can include logic to check the results of the
previous task before starting the next one and just abort the whole thing if
an error occurs.

For sure, the thread synchronization you've tried in the code you posted
already is wrong. It appears that you're polling (which is why the main UI
freezes up...you never leave the loop until all tasks are done), and you're
checking an unsynchronized flag (which isn't thread-safe).

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