在 x 分钟后停止执行代码

Stop execution of code in x minutes

我有一个应用程序,其中命令以 x 分钟的间隔发送到串行端口。代码:

int i = 0;

do
{
      // Send temperature
      com.SendComMessage(Temperature[i], Command[i]);

       // Start timer
       System.Timers.Timer t = new System.Timers.Timer();
       t.Elapsed += new TimerElapsedEventHandler();
       t.Interval = Convert.ToInt32(Time[i]);
       t.AutoReset = false;
       t.Enabled = true;

        // Tell CarbageCollector not to destroy the timer
        GC.KeepAlive(t);

        i++;

} while (i <= count);

我想停止执行循环,直到时间结束。

我考虑过使用线程,像这样:

System.Threading.Thread.Sleep(Convert.ToInt32(Time[i])*60);

但我可能不会在代码休眠时更新 GUI,因为串行端口会收到来自设备的响应。

我怎样才能做到这一点?

如果你想更新 GUI 那么你需要 运行 不同线程中的串行端口通信代码到 UI。

使用任务并行库(即 Task 对象,asyncawait)或类似 BackgroundWorker 的东西将通信代码转移到后台线程.

在您的后台线程中,您将有效地拥有一个向 COM 端口发送命令然后解码响应的循环。在该循环中,您可以在请求之间使用 Thread.Sleep(...)await Task.Delay(...) 到 "pause"。

然后 Steven Rands 已经使用 async/await 和 Task.Delay() 给了你一个很好的答案:

private async void button1_Click(object sender, EventArgs e)
{
    int i = 0;
    do
    {
        // Send temperature
        com.SendComMessage(Temperature[i], Command[i]);
        await Task.Delay(1000); // wait one second before continuing
        i++;
    } while (i <= count);
}

请注意该方法已用 async 标记,我们正在 await 调用 Task.Delay()。这将导致响应式 GUI 在继续下一次循环迭代之前等待一秒钟时仍然可以接收事件。

如果您需要将超时期限与 success/failure 类型的场景相结合,那么请考虑这样的事情:

    private System.Threading.ManualResetEvent MRE = new System.Threading.ManualResetEvent(false);

    private async void button1_Click(object sender, EventArgs e)
    {
        button1.Enabled = false;

        bool result = false;
        for (int i = 1; i <= 5; i++ )
        { 
            Console.WriteLine("Message " + i.ToString() + " Sent");

            MRE.Reset();
            await Task.Run(delegate()
            {
                result = MRE.WaitOne(TimeSpan.FromSeconds(10)); // wait up to ten seconds for MRE to be set
            });

            if (result)
            {
                Console.WriteLine("Success!");
            }
            else
            {
                Console.WriteLine("Timeout Fail");
            }
        }

        button1.Enabled = true;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        // simulated receipt of something
        Console.WriteLine("...bloop...");
        MRE.Set(); // tell the main loop it's okay to continue
    }