0

I have a code like this:

if (condition#1) {
   // step 2
   ConfigurazioneSA csa = new ConfigurazioneSA(...);
   WconfiguraSA.RunWorkerAsync(csa);
}
else
{
   // step 1
   PassaggioIE bo = new PassaggioIE(...);
   WpassIE.RunWorkerAsync(bo);

   if (condition#2) {
      // step 2
      ConfigurazioneSA csa = new ConfigurazioneSA(...);
      WconfiguraSA.RunWorkerAsync(csa);
   }
}

When execution flow is inside condition#1 branch, the step 1 block has been previously executed (in a previous execution of my application) so step 2 can be executed without any problem.

But, when execution flow is inside else branch I need to execute step 1 and when this step is completed I can execute step 2. Since I'm using BackgroundWorker as step 1 start, step 2starts immediately after causing error.

I would sinchronize this producer/consumer problem adding as less entropy as I can. All solutions that I found introduce a great amount of code, while I would a simply semaphore that avoid the step 2 execution until step 1 is not complete. Any ideas?

BAD_SEED
  • 4,840
  • 11
  • 53
  • 110

3 Answers3

1

I'll suggest you to use Tpl for this. This can be achieved easily.

    Task.Factory.StartNew(() =>
    {
        //Step1
    }).ContinueWith(antecedent =>  //executed after step1 is done
    {
        if (condition#2) 
        {
        // step 2
        }
    });

Also note you'll not get events like Progress and Completed, you've to sacrifice. Completed event is similar to ContinuationTask.

One more difference here is ContinuationTask will execute in threadpool thread, If you want it in UI thread use TaskScheduler.FromCurrentSynchronizationContext

Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
  • I've insert your code inside my else branch and then replace step1 and step2 with real code but seems already not in synchro :( – BAD_SEED Oct 02 '13 at 08:26
  • I can't get you, What happens? – Sriram Sakthivel Oct 02 '13 at 08:27
  • Nothing. As soon step1 starts step2 starts too (causing the same error like before)... – BAD_SEED Oct 02 '13 at 08:39
  • Replace step1 and step2 with codes in `DoWork` handlers, not `RunWorkerAsync`. – unarist Oct 02 '13 at 08:40
  • yes unarist is right, You've to use the code in `DoWork` in step1 – Sriram Sakthivel Oct 02 '13 at 08:53
  • This means that I should remove the previous event handling (from the doWork), and this will add entropy. What could I use to localize (as much as I can) the editing to that if/else branch? – BAD_SEED Oct 02 '13 at 09:39
  • In multithreaded application you can't expect anything to be synchronous. You can't guarantee that when if/else execute your `operation2` has finished executed already. Best way is to start async operations, then continue when async operation is done(that's what I provided as a solution). – Sriram Sakthivel Oct 02 '13 at 09:48
0

If you don't want to use Tasks, you can use BackgroundWorker.RunWorkerCompleted event raised when its execution is completed.

// step 1
PassaggioIE bo = new PassaggioIE(...);

WpassIE.RunWorkerCompleted += (sender, e) => {

    // You might want to add error handling code here.

    if (condition#2) {
        // step 2
        ConfigurazioneSA csa = new ConfigurazioneSA(...);
        WconfiguraSA.RunWorkerAsync(csa);
    }
}

WpassIE.RunWorkerAsync(bo);

But I think using TPL is better too.

unarist
  • 616
  • 8
  • 26
  • does the bo.RunWorkerCompleted create a mess with previously RunWorkerCompleted? – BAD_SEED Oct 02 '13 at 09:56
  • Oops, I thought `bo` is BackgroundWorker... If you use same BackgroundWorker many times, that's right. – unarist Oct 02 '13 at 10:56
  • For workaround, save lambda expression as delegate, then you can remove it from `RunWorkerCompleted`. If you can block this method while step1, `BackgroundWorker.IsBusy` is useful. – unarist Oct 02 '13 at 11:16
  • Should I write something like `while(!BackgroundWorker.IsBusy) {// step 2}` – BAD_SEED Oct 02 '13 at 12:47
  • Like `while(!BackgroundWorker.IsBusy) Application.DoEvents();`. See http://stackoverflow.com/questions/2183520/backgroundworkers-never-stop-being-busy. – unarist Oct 02 '13 at 16:13
  • It never goes inside the while? It looks like Background is stuck in busy mode! :( – BAD_SEED Oct 02 '13 at 16:46
  • oh...I made a mistake again. I'll write as new answer. – unarist Oct 02 '13 at 23:24
0

IsBusy example:

else
{
   // step 1
   PassaggioIE bo = new PassaggioIE(...);
   WpassIE.RunWorkerAsync(bo);

   // wait for WpassIE to complete
   while(WpassIE.IsBusy) Application.DoEvents();

   if (condition#2) {
      // step 2
      ConfigurazioneSA csa = new ConfigurazioneSA(...);
      WconfiguraSA.RunWorkerAsync(csa);
   }
}

In this solution, you've to wait WpassIE completion.

and don't use Thread.Sleep instead of Application.DoEvents because it causes problem like BackgroundWorkers never stop being busy.

Community
  • 1
  • 1
unarist
  • 616
  • 8
  • 26