3

Ok. I have a program that monitors 2 COM ports. One is hooked to a scale and the other is hooked to a modbus board.

My problem is in the COM port attached to the modbus board. My program is reading a sensor (on the modbus board) every 100MS. It returns a 0 or 1 (over the COM port) to determine whether the sensor is blocked. If it is blocked, a signal is sent over the port to the board.

My problem is I can't quit monitoring the sensor, but I have to be sure the com port is not in use before sending my other signal.

The routine that monitors the sensor is on a backgroundworker thread. Once the sensor is tripped, another thread is spawned that sends a signal to the modbus board. So I need to pause the "sensor thread" while I'm sending a signal to the board. How would I go about doing this?

Remember it is a BackgroundWorker, so Thread.Join is not an option.

Here is my code:

private void SensorThread_DoWork(object sender, DoWorkEventArgs e)
    {
        if (SensorThread.CancellationPending == true)
            e.Cancel = true;
        else
        {
            ReadSensor();
        }    
    }

The RunWorkerCompleted for this thread just restarts the thread. The following thread is constantly monitoring the "sensorstatus" to see when the sensor is blocked:

public void ScaleThread_DoWork(object sender, DoWorkEventArgs e)
    {
        if (ScaleThread.CancellationPending == true)
        {
            e.Cancel = true;
        }
        else
        {
            //sensor is blocked
            if (sensorstatus == 0)
            {
                ReadScale();
                prevgate = gate;
                gate = DetermineGate();
                //SaveData();
                SetOpenDelay();
                SetDuration();
                //no gate was selected, meat out of range, runs off end
                if (gate == 0)
                {
                    txtStatus.Invoke(new UpdateStatusCallback(UpdateStatus), new object[] { meatweight.ToString() + 
                                                                                    "lbs is out of range"});
                }
                else
                {
                    //this triggers a thread to send a signal to the modbus board
                    gateTimer.Start();
                }
            }
        }
    }

The RunWorkerCompleted for this restarts this thread, making it a loop

CSharpDev
  • 869
  • 1
  • 13
  • 22
  • 3
    For a task like that, I think `BackgroundWorker` is the worst solution you can choose. If you have something that needs to be monitored every `x` seconds, a traditional `Thread` with a `while` loop and a `Thread.Sleep(x);` is much more suitable... – Thorsten Dittmar Mar 29 '12 at 20:14

1 Answers1

5

Create a single thread responsible for ALL send operations. Implement a Queue that feeds this thread with messages to send to the device. You can use the new BlockingCollection<T> to implement this easily.

OR, using TPL, create a TaskScheduler with a limited degree of parallelism of 1 as shown here:- http://msdn.microsoft.com/en-us/library/ee789351.aspx

Now you can simply fire of Tasks to send to the device and they will execute sequentially.

Unless there is some need to communicate information between the sender and the reader I would implement the reader operation on its own separate thread.

Ian Mercer
  • 38,490
  • 8
  • 97
  • 133