c# - 需要点击按钮两次才能生效
问题描述
该应用程序是一个机器控件,因此它需要访问 ui 以显示状态等(我知道,这违背了将 UI 和工作代码分开的建议,但至少目前是这样)。问题归结为:当一个按钮事件处理程序未完成时,需要单击另一个按钮两次。第一次单击将焦点放在按钮上,下一次单击会触发事件。
这是简化到极端的问题。有两个按钮和一个标签。停止按钮需要单击两次才能停止机器:
bool Stop = true;
private void Start_button_Click(object sender, EventArgs e)
{
RunMachine();
}
private void Stop_button_Click(object sender, EventArgs e)
{
Stop = true;
}
private void RunMachine()
{
Stop = false;
Status_label.Text = "Running";
do
{
Application.DoEvents();
Thread.Sleep(50);
}
while (!Stop);
Status_label.Text = "Stopped";
}
如何使按钮对第一次点击做出反应?
解决方案
DoEvents()不好。不要使用它。
如果您必须使用它(例如作为解决方法),那么您正在增加技术债务并可能在未来支付,类似于您的情况。
更好的方法是在任务内运行工作并使用取消令牌,但在您的情况下,所需的最小修改是这样的(将async修饰符添加到方法中):
while (!Stop)
{
await Task.Delay(50);
// or
await Task.Run(() => Thread.Sleep(50));
}
UI 现在应该可以响应了。
后者是模拟同步代码,把它代替Sleep
,如果需要修改UI不要忘记调用。
推荐阅读
- sql - oracle中如何对多个表进行动态选择查询?使用表名和列名作为其他表的值?
- arduino - 通过 ESP8266 Webserver 控制 Arduino 引脚
- php - 无法将类型 ... 的 PHP 值转换为类型 ...。应为以下类型之一:null、DateTime
- c++ - 如何获得带有引号的句子?
- git - 弹出并重放一堆 git 提交
- vba - 根据货币乘以每个单元格
- karma-jasmine - 尽管在 fakeAsync 中刷新,但计时器仍在队列中
- sql - 有没有办法在 Oracle 19 中向 JSON 数组添加/附加值?
- c++ - 数学函数的不一致死码消除
- javascript - 如何将流从客户端上传并保存到 mp4 中的节点服务器