在x分钟内停止执行代码

时间:2015-01-29 13:43:42

标签: c# multithreading timer

我有一个应用程序,其中命令以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,因为串口会收到设备的响应。

我怎么能做到这一点?

2 个答案:

答案 0 :(得分:0)

如果要更新GUI,则需要在与UI不同的线程中运行串口通信代码。

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

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

答案 1 :(得分:0)

然后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在等待一秒钟之前仍然可以接收事件,然后再继续循环的下一次迭代。

如果您需要将超时时间与成功/失败类型方案相结合,那么请考虑以下内容:

    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
    }