【问题标题】:How to run process only once even if condition remains true即使条件保持为真,如何只运行一次进程
【发布时间】:2020-03-10 11:42:30
【问题描述】:

我有一个抓取图像并对其进行处理的函数。该功能在从 PLC 接收到过程信号时起作用。 我有一个计时器,它不断检查来自 PLC 的信号。 一旦我收到来自 PLC 的信号,图像就会被抓取并处理,但信号保持真实,直到处理完成并将结果发送给机器人,之后机器人发送停止信号。 有时,处理发生得很快,在机器人发出停止信号之前,该函数再次运行。

这是定时器代码:

     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();    
        }
    }

尽管信号仍显示“进程”(条件保持为真),但如何使该方法只运行一次?并等到信号停止(条件变为假)并接收到下一个过程信号(条件再次变为真?

【问题讨论】:

  • 你不能只使用一个布尔字段,比如_isRunning吗?或者如果这是多线程的,使用信号量?
  • 顺便说一句,Thread.Sleep(200); 你为什么要休眠 UI 线程?
  • 第一个想法是:如果 chkSignal 返回,禁用计时器。然后做魔术,然后检查信号下降,然后重新启动计时器。不过,尚不清楚您是否对时间有一些要求。所以这只是一个粗略的想法,可能需要认真调整。
  • @Çöđěxěŕ 抓取图像后,我想在处理开始前等待几毫秒。
  • 我不明白你的代码。 chksignal 是阻塞呼叫吗? chksignal 将 textBox8.Text 设置为启动处理的“处理”吗?听起来您需要检查上升沿。

标签: c# .net if-statement timer conditional-statements


【解决方案1】:

你能设置一个像下面这样的标志吗?

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

    if (textBox8.Text.Contains("process")   && flag1==true) //
    {
        flag1=false
        totalsheetcount++;

        grab_image();
        Thread.Sleep(200);               
        processimage();  
        flag1=true  
    }
}

【讨论】:

    【解决方案2】:

    在一个循环中,您必须获取所有信号等。 你可以使用布尔值。就是这个。

    
    private void timer3_Tick(object sender, EventArgs e)
        {
    
    var maxsheet=30; //write correct!
    bool processed=false;
    
    while(totalsheetcount<maxsheet)
    {
            chksignal_robot(); //keep checking signal           
    
            if (textBox8.Text.Contains("process")) //
            {
                totalsheetcount++;
    
                grab_image();
                Thread.Sleep(200);               
                if(!processed)
                 processimage(); 
                processed=true;   
            }
    }
        }
    

    【讨论】:

      【解决方案3】:

      我不确定我是否理解您的代码。但是你可以试试这个。这是上升沿的经典检查(假 -> 真)。

      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();
          }
      }
      

      补充说明:

      Thread.Sleep(200) 将冻结您的程序。更优雅的解决方案是将 Task.Delay() 与 async/await 关键字结合使用。这不会阻塞你的 UI 线程。

      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
      }
      

      【讨论】:

      • 嗨,bool newSignal = chksignal_robot();不起作用,它说它不能将 void 转换为布尔值。 chksignal_robot() 保持与 PLC 通信,以便文本框 8 接收关键字“进程”。使用异步任务,感谢您的建议。
      • @Roshan 所以 chksignal_robot 在信号到来时设置 textBox8 = "process"?当停止信号到来时,它会将 textBox8 设置为别的东西吗?到什么? textBox8 =“停止”?您如何在应用程序中看到停止信号来了?
      • 嗨,停止信号设置 textbox8 = "0"。
      • 工作完美,感谢您一直以来的帮助。
      • @Roshan 很高兴听到。下次尝试添加重要的细节,例如 chksignal 将文本框更改为问题中的这个和那个。这使人们更容易理解问题和代码。这将大大增加获得答案的机会,并且您会更快地获得答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-17
      • 2019-07-06
      • 2012-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多