如何以不完全低效的方式实现忙碌等待?我面临的问题是我只能以拉动的方式加载模型的数据,这意味着我必须以连续的方式调用getXYZ()方法。
这对于用户交互来说不够快,但是很快就会发生,当GUI中的状态发生变化时,可以注意到模型并且getXYZ()方法接收到新状态。
我的方法就是:
while (c.hasChanged()) {
Thread.sleep(500);
}
updateData();
有更好的机制吗?
答案 0 :(得分:5)
您的问题似乎可以通过Threading解决。
在WPF中你可以这样做:
Thread t = new Thread((ThreadStart)delegate() {
while (true) {
Thread.sleep(500);
if (c.hasChanged())
Dispatcher.Invoke((Action)delegate() {updateData();});
}
}).Start();
在WinForms中
Thread t = new Thread((ThreadStart)delegate() {
while (true) {
Thread.sleep(500);
// this must derive from Control
if (c.hasChanged())
this.Invoke((Action)delegate() {updateData();});
}
}).Start();
Invoke可能缺少参数(在调用UI线程上执行代码时需要这些参数),但我是从大脑写的,所以没有智能感知:D
在.NET 4中,您可以使用TaskFactory.StartNew而不是自己生成线程。 在.Net< = 4中,您可以使用TreadPool作为线程。 但是我记得你需要立即运行它,因为你希望它尽快检查并且线程池不会向你保证(它可能已经满了,但不太可能:-)。 只是不要做愚蠢的事情,比如在循环中产生更多的东西!
在线程中你应该像
一样检查while (!Closing)
这样线程可以在您需要时完成,而不必诉诸t.Abort();
之类的错误
退出时将Closing设置为true并执行t.Join()
以关闭检查程序线程。
编辑:
我忘了说Closing应该是一个bool属性或VOLATILE布尔值,而不是一个简单的布尔值,因为你不能确保线程可以完成(如果你是关闭应用程序,但最好按照您的意愿完成它们)。 volatile关键字旨在防止(伪)编译器对假定变量值无法更改的代码应用任何优化
答案 1 :(得分:2)
从您的帖子中确切地知道您要做的事情并不清楚,但听起来您应该将模型/服务调用放在单独的线程上(通过后台工作程序或异步委托)并使用模型/服务的回调调用在完成后通知UI。然后,您的UI线程可以执行繁忙的操作,例如显示进度条,但不会变得无法响应。
答案 2 :(得分:2)
如果从GUI进行轮询,请使用(WinForms)计时器。
如果这是某种背景过程,你的睡眠()可能是较小的邪恶。
答案 3 :(得分:0)
明确的忙碌等待是邪恶的,必须尽可能避免。
如果无法避免,请使用Observer设计模式构建应用程序,并将感兴趣的对象注册到执行轮询的对象,由线程支持。
这样你就拥有了一个干净的设计,将丑陋的东西限制在一个地方。