ManualResetEvent with a BackgroundWorker : Current thread is busy while WaitOne()?

1.2k views Asked by At

Imagine following situation:

  1. I got a signal on the ui thread from a third party server.

  2. I start a BackgroundWorker with RunAsync to fetch data from a database and another async thread, which shall poll another hardware and receive signals, also not in ui thread

  3. Inside the bg's DoWork eventhandler I call manualresetEvent.Reset(). Then I call the data-fetching method, and then I call manualresetEvent.Set() and in the end I call the method METH_UI_1 on the ui thread by invoking it.

  4. The other hardware thread shall receive hardware-data, which then itself is passed via Invoke to the ui into the ui thread to set some ui-elements periodically depending on the hardware-data I get.

  5. The data from database can also not be fetched yet, but the ui must react to the hardware-data, which is polled by the second async thread.

  6. In METH_UI_1 I call manualresetEvent.WaitOne();

Some times I get the exception, that the background worker is busy and cannot run multiple tasks concurrently.

a) Is there really a need for a ManualResetEvent object ?

b) Would it be enough, to check for the isBusy property in order to issue WaitOne() only, when the background worker is no more busy ?


UPDATE: CODE.

MainForm.cs (event handler of third party hw-vendor, component, handled in ui thread)

 private void thrdptyPlcGotData(object sender, thrdptyPlcGotDataEventArgs e)
    {
        string strError = string.Empty;
        bool blNotReadyYet = false;            

        try
        {
            ThrdPtyPlcIfs.DataSetthrdptyPlc ds;

                ds = new ThrdPtyPlcIfs.Dataset();
                e.FillDataToTDataSet(ds);
               ThrdPtyPlcIfs.Statics.SaveDataSet(ds, CLStatics.FileName);


                               if (this.ValidateDsDetail(ds))
                                {
                                    // begin async work..... ask db, continue asking scale-> inside got weight of scale the rest is handled ( using or trashing db data )
                                    this.ExtractDataOfDataSet(ds);
                                    this.bgWorkerStart_Get_Data.RunWorkerAsync();                                        

                                    _oAsyncScaleManager.StartThread();
                                 }
         }
}

runworkerasynch does this:

private void bgWorkerStart_Get_Data_RFC_DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {

            _blnStart_Get_Data_RFC = this.StartGetData_RFC(null);
        }
        catch (Exception ex)
        {
            LogExcep(ex);
            _blnStart_Get_Data_RFC = false;
        }            
    }

WorkCompleted EventHandler of the BackGroundWorker:

 private void bgWorkerStart_Get_Data_RFC_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {            
        try
        {  
            if (InvokeRequired)
            {
                this.Invoke((MethodInvoker)delegate()
                {
                    this.ApplyDbDataToUi();
                }
                            );
            }
            else
            {
                this.ApplyDbDataToUi();
            }

        }
        catch (Exception ex)
        {
            LogAndShowExep(ex);
        }
    }
1

There are 1 answers

2
TimD On

As rare as it might be , its possible the BackgrounWorker isn't finished when you set manualresetEvent inside the dowork method block. If its at the very end , I would hook into the backgroundworker workcompleted event and set it in there.