【问题标题】:How to run a while loop just once even when the condition stays true for more time than required to complete the loop即使条件保持为真的时间超过完成循环所需的时间,如何只运行一次while循环
【发布时间】:2017-12-15 05:38:00
【问题描述】:

我有一个应用程序,我正在检查从 PLC 读取的信号是真还是假,如果它是真的 - 它会进行一组计算,如果它是假的,它会等待信号。我正在使用一个while循环来做到这一点。但问题是真实状态会保持 1000 毫秒,循环在不到 100 毫秒内完成,因此它会再次返回,并且由于状态为真,它会再次处理它。因此,对于我从 PLC 接收到的 1 个信号,循环运行大约 9-10 次。我尝试添加 thread.sleep 但它仍然不止一次处理它。我希望循环在状态为真时运行一次,然后等待它再次变为真。

代码如下:

 bool isRunning = true;

    private void WorkThreadFunction()
    {
        while (isRunning)
        {

             if (ethernetIPforSLCMicroCom1.Read("B3:254/1") == "True")
            {

                stopWatch = Stopwatch.StartNew();

                int isTriggered;

                Int32.TryParse(trigger, out isTriggered);

                timer1.Start();


                Thread.Sleep(10);
                serialcheck();

                System.GC.Collect();

        }

    }

【问题讨论】:

  • 您需要通过存储和比较来检测变化。
  • 那么你不使用循环,你使用事件来进行这种行为。
  • 我也尝试在计时器内移动整个 if 语句。同样的事情也会发生。您能否提供您的建议的示例代码?

标签: c# methods while-loop


【解决方案1】:

我正在处理一个从 GPIO 引脚读取信号的程序,您的问题与我的非常相似,也就是防止单个开启信号被多次处理。我的解决方法是先确保信号关闭,然后再去检查信号是否再次开启。

while (isRunning)
{
    var signal = ethernetIPforSLCMicroCom1.Read("B3:254/1");
    if (signal == "True")
    {
        //do your stuff
    }

    while (signal == "True")
        signal = ethernetIPforSLCMicroCom1.Read("B3:254/1");
}

内部循环将等待信号转为除"True" 之外的其他值,然后再继续执行任何其他操作。

【讨论】:

  • 嗨,我尝试了你的建议,但是当循环运行时,应用程序会冻结。
  • 如果你的程序中还有其他部分,你可能应该在一个线程中进行。
  • 嗨,我创建了一个线程来处理这个。它现在运行良好,除了一个小新问题。第一次信号状态为真..它什么都不做。从第二个信号开始,它开始工作。因此,第一个信号的结果是误报。
  • 您可能应该运行一个调试器来查看您是否真的在第一个真正的信号上收到了一个真正的信号。只有当信号变为真时,内部循环才会运行,没有循环,它与您的旧代码相同。
【解决方案2】:

为了等待它再次为真,您需要跟踪它是否为假。

bool isRunning = true;
bool signalHasBeenFalse = true;

private void WorkThreadFunction()
{
    while (isRunning)
    {

         if (ethernetIPforSLCMicroCom1.Read("B3:254/1") == "True" && hasBeenFalse )
        {
            signalHasBeenFalse = false;

            stopWatch = Stopwatch.StartNew();

            int isTriggered;

            Int32.TryParse(trigger, out isTriggered);

            timer1.Start();


            Thread.Sleep(10);
            serialcheck();

            System.GC.Collect();

        }

        if ( ethernetIPforSLCMicroCom1.Read("B3:254/1") != "True" ) 
        {
            signalHasBeenFalse = true;
        }

    }
}

【讨论】:

  • 您好,我尝试了您的建议。但是,就像@lamandy 的建议一样,它有效,除了一个小新问题。第一次信号状态为真..它什么都不做。从第二个信号开始,它开始工作。因此,第一个信号的结果是误报
【解决方案3】:

如果我没看错,您只需在 while 循环中满足您的条件的地方添加一个 break;

我这里做了一个例子:https://dotnetfiddle.net/FsGryD

我还要补充一点,您可能会考虑使用 SpinWait.SpinUntil(<boolean_condition>) 是否是更好的选择。 (https://msdn.microsoft.com/en-us/library/system.threading.spinwait(v=vs.110).aspx)。

我之前在多线程/IO 等待函数中使用过它来等待来自设备的信号。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多