忙着等待C#

时间:2011-04-30 06:28:17

标签: c# multithreading concurrency

如何以不完全低效的方式实现忙碌等待?我面临的问题是我只能以拉动的方式加载模型的数据,这意味着我必须以连续的方式调用getXYZ()方法。

这对于用户交互来说不够快,但是很快就会发生,当GUI中的状态发生变化时,可以注意到模型并且getXYZ()方法接收到新状态。

我的方法就是:

while (c.hasChanged()) {
   Thread.sleep(500);
}
updateData();

有更好的机制吗?

4 个答案:

答案 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设计模式构建应用程序,并将感兴趣的对象注册到执行轮询的对象,由线程支持。

这样你就拥有了一个干净的设计,将丑陋的东西限制在一个地方。