同步后台工作者

时间:2013-10-02 07:23:19

标签: c# backgroundworker .net-4.5

我有这样的代码:

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);
   }
}

当执行流程在condition#1分支内部时,先前已执行step 1块(在我之前的应用程序执行中),因此step 2可以毫无问题地执行。

但是,当执行流程在else分支内部时,我需要执行step 1,当此步骤完成后,我可以执行step 2。由于我使用BackgroundWorker作为第1步启动,step 2会在导致错误后立即启动。

我会将这个生产者/消费者问题同步化为尽可能少的熵。我发现的所有解决方案都引入了大量代码,而我只是简单的信号量,在step 2未完成之前避免执行step 1。有什么想法吗?

3 个答案:

答案 0 :(得分:1)

我建议您使用Tpl。这很容易实现。

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

另请注意,您不会获得ProgressCompleted等事件,您必须牺牲。 Completed事件类似于ContinuationTask

这里的另一个区别是ContinuationTask将在线程池线程中执行,如果你想在UI线程中使用它TaskScheduler.FromCurrentSynchronizationContext

答案 1 :(得分:0)

如果您不想使用任务,则可以在执行完成时使用BackgroundWorker.RunWorkerCompleted事件。

// 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);

但我认为使用TPL也更好。

答案 2 :(得分:0)

IsBusy示例:

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);
   }
}

在此解决方案中,您必须等待WpassIE完成。

并且不要使用Thread.Sleep代替Application.DoEvents,因为它会导致问题BackgroundWorkers never stop being busy