2011-04-30 102 views
0

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

对于用户交互,这必须发生得不够快,但足够快,当GUI中的状态发生变化时,模型可以被注意到,并且getXYZ()方法接收到新状态。

我的做法仅仅是:

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

有没有更好的机制?

+2

看看后台线程(BackgroundWorker的或裸线程) – Flawless 2011-04-30 06:34:21

+0

请说明什么样的应用是轮询模式在这里。 – 2011-04-30 08:25:49

回答

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线程上的代码),但我m写这从我的大脑,所以没有intellisense处置:D

在.NET 4中,您可以使用TaskFactory.StartNew,而不是自己产生一个线程。 在.net < = 4中,您可以使用线程的TreadPool。 但是我记得你需要立即执行这个操作,因为你希望它尽快在线检查,线程池不会向你保证(它可能已经满了,但不是很可能:-)。 只是不要做一些愚蠢的事情,比如在一个循环中产生更多的东西!

和线程里面你应该把像

while (!Closing) 

检查,使线即可完成,当你需要它没有退出时把截止到真实而不必诉诸坏事像t.Abort(); 的执行t.Join()关闭检查程序线程。

编辑:

我忘了说,闭幕式应该是一个布尔属性或VOLATILE布尔值,而不是一个简单的布尔,因为你不会保证线程所能完成(以及它会在如果您正在关闭应用程序,但最好按照您的意愿完成)。 volatile关键字旨在防止(伪)编译器对假定变量值无法更改的代码应用任何优化

+0

就我的理解而言,除了最琐碎的程序以外,永远不应该使用VOLATILE。这不仅对AMD和安腾处理器都不安全。约瑟夫阿尔巴哈利也得到了英特尔处理器的简单测试代码,表明挥发是这里不安全或者 - http://www.albahari.com/threading/part4.aspx#_The_volatile_keyword – Johnv2020 2011-05-02 16:11:25

+0

@约翰我同意你的看法,但由于这种特殊的挥发性布尔将在一个循环中读取它不是是否会被读取真的那么重要错误一次或两次(如果这是并不重要,因为高速缓存一致性或什么的,在某些时候它会重新读取)。如果编译器用while(true)替换while(bClos​​ing)会出现什么问题。我不是框架专家,但文档摘录说编译器永远不会对volatile变量进行优化。无论如何,最好的办法是使这个财产。 – 2011-05-14 19:08:51

2

从你的帖子中不清楚你正在尝试做什么,但它听起来像你应该把你的模型/服务调用放在一个单独的线程(通过后台工作者或异步委托),并使用模型/服务调用在完成时通知UI。然后,您的UI线程可以执行繁忙的工作,例如显示进度条,但不会变得无法响应。

2

如果您要从GUI进行轮询,请使用(WinForms)Timer。

如果这是某种背景过程,您的睡眠()可能是较小的邪恶。

0

明确忙等待是邪恶的,必须尽量避免。

如果无法避开它,然后使用观察者设计模式构建应用程序并注册感兴趣的对象到执行轮询,由一个线程支持的对象。

这样,你有一个干净的设计,围丑陋的东西,在一个地方。