-1
//Button need DataRecieved  event handler
private void LoggedDataBtn_Click(object sender, EventArgs e)
{
    //When LoggDataBtn is pressed it Send the command LogToShow to  device
    string LoggedDataTOshow = "?R\r\n";
    string commForMeter = string.Format(LoggedDataTOshow);

    try
    {
        if (serialPortForApp.IsOpen)
        {
            Thread.Sleep(2000);
            serialPortForApp.Write(LoggedDataTOshow);
        }
    }
    catch (Exception)
    {
        ShowDataInScreenTxtb.Text = "TimeOUT Exception: Error for requested command";
    }
}

//button does not need DataRecieved handler to display but create conflict 
//for those that need it
private void GLPBtn_Click(object sender, EventArgs e)
{
    //send command to instrument
    string GLPCommand = "?G\r\n";
    string GLPToShow = String.Format(GLPCommand);

    try
    {
        if (serialPortForApp.IsOpen)
        {
            Thread.Sleep(2000);
            //write command to port
            serialPortForApp.Write(GLPToShow);
        }
    }
    catch
    {
        //MessageBox error if data reading is not posible
        ShowDataInScreenTxtb.Text = "TimeOUT Exception";
    }

    while (glpShowInMainForm.DataToSetandGet != "ENDS\r")
    {
        serialPortForApp.Write("\r");
        DataToSetandGet = serialPortForApp.ReadExisting();
        ShowDataInScreenTxtb.AppendText(DataToSetandGet.Replace("\r", "\r\n"));
    }
}


//event handler
private void SerialPortInApp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    try
    {
        // SerialPort1_DataReceived handles to recieve data from device connected to Port
        Thread.Sleep(500);
        DataToSetandGet = serialPortForApp.ReadExisting();
        // Invokes the delegate on the UI thread, and sends the data that was received to the invoked method.  
        // ---- The "SerialPortInApp_DataReceived" method will be executed on the UI thread which allows populating of the textbox.  
        if (this.InvokeRequired)
        {
            Invoke(new MethodInvoker(delegate { 
                ShowDataInScreenTxtb.AppendText(DataToSetandGet.Replace("\r", "\r\n")); 
            }));
        }

        //The requested command is responded by the invoke method sending back the answer requested to display into the Textbox( DisplayDataTxB)
        ShowDataInScreenTxtb.AppendText(DataToSetandGet.Replace("\r", "\r\n"));

        //////display message(DataReadingStatusLbl) everytime data is retreiving from through the port 
        //   DataReadingStatusLbl.Text = "Retrieving Data from TPS Instrument -->>";
    }
    catch (Exception)
    {
        ShowDataInScreenTxtb.Text = "TimeOUT Exception: Error Port ";
    }
}

private void OpenPortBtn_Click(object sender, EventArgs e)
{
    //Connect Port Button allows to connect the current device base on Port and Raud settings
    try
    {
        if (PortIndexCbx.Text == "" || BaudRateIndexCbx.Text == "")
        {
            ShowDataInScreenTxtb.Text = "Set Up your Port Settings";                    
            //Error message to user to set up port connection if empty selection
        }
        else    
        {
            //Get Serial Port index settings to display for users 
            serialPortForApp.PortName = PortIndexCbx.Text;                       


            serialPortForApp.BaudRate = Convert.ToInt32(BaudRateIndexCbx.Text);      
            serialPortForApp.DataBits = 8;                                    
            serialPortForApp.Parity = Parity.None;                            
            serialPortForApp.StopBits = StopBits.One;                         
            serialPortForApp.Handshake = Handshake.XOnXOff;                   

            //Open serial Port to allow communication between PC and device 
            //DataReceived Implemented to read from Port sending and recieving the 
            buttons command requested
            //To receive data, we will need to create an EventHandler for the 
            // "SerialDataReceivedEventHandler"

            //I delete this and GLPBtn_Click responds and work without it, but I need 
            //both buttons to work because LoggedDataBtn_Click need this event to 
            //display responds

            serialPortForApp.DataReceived += new 
            SerialDataReceivedEventHandler(SerialPortInApp_DataReceived);

            serialPortForApp.ReadTimeout = 500;
            serialPortForApp.WriteTimeout = 500;

            //serialPortForApp.RtsEnable = true;
            //serialPortForApp.DtrEnable = true;

            //Once Serial port and baud rate setting are set, 
            //connection is ready to use 
            //Open serial port for communication between device and PC
            serialPortForApp.Open();

            //Connect and close connection buttons Behaviour
            progressBarPortAccess.Value = 100;                   
            OpenPortBtn.Enabled = false;                   
            ClosePortBtn.Enabled = true;                   
            ShowDataInScreenTxtb.Enabled = true;
            ShowDataInScreenTxtb.Text = "";

            DataReadingStatusLbl.Text = "Port is Connected";
        }
    }
    catch (UnauthorizedAccessException)
    {
        ShowDataInScreenTxtb.Text = "Unauthorized Port Access";
    }
}

//how to create a switch case or to define that button values are different to read and display. some buttons work with datarecived event and others buttons don't need it, but create a conflict for those that need ReadExiting in the datarecieved event handler like my LoggedDataBtn_Click other buttons need the ReadExisted into the button_click method instead of using the datarecieved event like my GLPBtn_Click.

Please how to fix this conflict thank you

Baddack
  • 1,947
  • 1
  • 24
  • 33
JimB
  • 11
  • 5

1 Answers1

0

In order to do this properly, you really need a state machine and delegates (call backs) in your datarecieved event that run the correct function based on which state you are in. In your case, pressing buttons on the gui could put it into a state. I have a pretty good write up here: https://stackoverflow.com/a/38536373/2009197

Baddack
  • 1,947
  • 1
  • 24
  • 33
  • HI Baddak Thank for the answer. I start to reorganize the code making the enum as the stateForButtons and direct the commads button to the specific calling methods in the switch case. Please if you have advice for how to stop that while loop in GLPBtn_Click I wiil appreciate. It suppose to finish if it found the ENDS\r but it continues. That is how my application crashes – JimB Jul 26 '18 at 04:58
  • Hi @JimB, the background worker has a `CancelAsync()` function, when set it tells the background worker to cancel. In your while loop you'll want to check `if (backgroundWorker1.CancellationPending) break;` and that will exit the while loop. Hope this helps. – Baddack Jul 26 '18 at 14:56
  • Thank you Baddak I implement the Enum ButtonState for my DataRecieved Event and it works perfectly. thanks mate. – JimB Aug 03 '18 at 00:30