Search code examples
c#timer

How I can change backColor of a button for a fixed time?


I want to change BackColor of a Button for a fixed time when a certain value comes from a serial port. I set the Timer object here:

public formLabel()
{
    InitializeComponent();
    // ...
    timerColor.Tick += timerColor_Tick;
    timerColor.Interval = 3000;
}

Then, when I receive signal from a serial port:

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    string indata = sp.ReadExisting();
    MessageBox.Show("Dati Ricevuti: " + indata);
    if (indata.CompareTo("K") == 0)
    {
        timerColor.Enabled = true;
        btnEsito.BackColor = Color.Green;
        btnEsito.Text = "GOOD";
        // Do something
    }
    if (indata.CompareTo("O") == 0)
    {
        timerColor.Enabled = true;
        btnEsito.BackColor = Color.Red;
        btnEsito.Text = "NO GOOD";
    }
}

and here is the method to stop the timer:

private void timerColor_Tick(object sender, EventArgs e)
{
    MessageBox.Show("HERE!");
    timerColor.Enabled = false;
    btnEsito.BackColor = Color.White;
}

BackColor of btnEsito becomes Green or Red based on the type of signal I receive but the program doesn't show the message "HERE!", and the button doesn't come back White.

Could anyone help me?


Solution

  • The System.Windows.Forms.Timer is designed for single threaded use & needs to be started & stopped on the UI thread. You are trying to start the timer on a separate thread, so you need to ensure modifying the timer Enabled property is done on the UI thread. You could do this by creating a delegate method & invoking that from your event handlers - possibly something like this :

    delegate void TimerDelegate(bool Enable);
    private void ControlTimer(bool Enable)
    {
      timerColor.Enabled = Enable;
    }
    
    private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        string indata = sp.ReadExisting();
        MessageBox.Show("Dati Ricevuti: " + indata);
        if (indata.CompareTo("K") == 0)
        {
            Invoke((TimerDelegate)ControlTimer, true);
            btnEsito.BackColor = Color.Green;
            btnEsito.Text = "GOOD";
            // Do something
        }
        if (indata.CompareTo("O") == 0)
        {
            Invoke((TimerDelegate)ControlTimer, true);
            btnEsito.BackColor = Color.Red;
            btnEsito.Text = "NO GOOD";
        }
    }
    
    private void timerColor_Tick(object sender, EventArgs e)
    {
        MessageBox.Show("HERE!");
        Invoke((TimerDelegate)ControlTimer, false);
        btnEsito.BackColor = Color.White;
    }