在 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
对象,async
和 await
)或类似 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
}
我有一个应用程序,其中命令以 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
对象,async
和 await
)或类似 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
}