Search code examples
c#.netif-statementtimerconditional-statements

How to run process only once even if condition remains true


I have a function which grabs an image and processes it. The function works when a process signal is received from a PLC. I have a timer which keeps checking for signal from PLC. Once I receive the signal from PLC, the image is grabbed and processed, but the signal remains true till the processing is finished and the result is sent to robot, after which the robot sends a stop signal. Sometimes, the processing happens quickly and before the robot could send the stop signal, the function runs again.

Here is the timer code:

     private void timer3_Tick(object sender, EventArgs e)
    {
        chksignal_robot(); //keep checking signal           

        if (textBox8.Text.Contains("process")) //
        {
            totalsheetcount++;

            grab_image();
            Thread.Sleep(200);               
            processimage();    
        }
    }

How do I make the method run just once although the signal still shows "process"(condition remains true)? and wait till the signal goes stop(condition goes false) and next process signal is received(condition becomes true again?


Solution

  • I am not sure if i understood your code. But you could try this. It is a classical check for a rising edge (false -> true).

    bool _oldSignal;
    
    private void timer3_Tick(object sender, EventArgs e)
    {
        chksignal_robot(); //keep checking signal    
    
        var newSignal = textBox8.Text.Contains("process");
        var isRisingEdge = newSignal && (_oldSignal == false);
        _oldSignal = newSignal;
    
        if (isRisingEdge) //
        {
            totalsheetcount++;
    
            grab_image();
            Thread.Sleep(200);
            processimage();
        }
    }
    

    Additional Note:

    Thread.Sleep(200) will freeze your program. A more elegant solution is using Task.Delay() in combination with async/await keywords. This wont block your UI-Thread.

    private async void timer3_Tick(object sender, EventArgs e)
    {
       // do some stuff
       await Task.Delay(200);  // wait 200 ms without freezing the UI.
       // do stuff after the 200 ms delay
    }