我有一个应用程序,其中命令以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,因为串口会收到设备的响应。
我怎么能做到这一点?
答案 0 :(得分:0)
如果要更新GUI,则需要在与UI不同的线程中运行串口通信代码。
使用任务并行库(即Task
对象,async
和await
)或类似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
}