C# 忙等待

发布于 2024-11-04 02:23:35 字数 285 浏览 2 评论 0原文

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

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

我的方法很简单:

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

是否有更好的机制?

How do you implement busy waiting in a not total inefficient way? I am facing the issue that I can load the data of my model only in a pull manner, which means I have to invoke getXYZ() methods in a continuous way.

This has to happen not fast enough for user interaction, but fast enought, that when a state in the GUI is changed, the model can be noticed and the new state is received by the getXYZ() methods.

My approach simply be:

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

Are there better mechanisms?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

紅太極 2024-11-11 02:23:35

您的问题似乎可以通过 线程

在 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();

调用 可能缺少参数(这是在调用 UI 线程上执行代码所必需的)但我是从我的大脑中编写此内容,因此没有可用的智能感知:D

在 .NET 4 中,您可以使用 TaskFactory.StartNew 而不是自己生成一个线程。
在 .Net <= 4 中,您可以使用 TreadPool 为线程。
但是我记得您需要立即运行它,因为您希望它尽快进行检查,并且线程池不会向您保证(它可能已经满了,但不太可能:-)。
只是不要做愚蠢的事情,比如循环生成更多它们!

在线程内部,您应该进行类似的检查

while (!Closing)

,以便线程可以在需要时完成,而不必求助于诸如 t.Abort(); 之类的坏东西
退出时将 Closing 设置为 true 并执行 t.Join() 来关闭检查器线程。

编辑:

我忘了说 Closing 应该是 bool 属性或 VOLATILE 布尔值,不是一个简单的布尔值,因为您无法确保线程能够完成(如果您正在关闭应用程序,那么它会完成,但最好让它们按您的意愿完成)。 volatile 关键字旨在防止(伪)编译器对假设变量值无法更改的代码应用任何优化

Your problem seems to be solvable with Threading.

In WPF you can do:

Thread t = new Thread((ThreadStart)delegate() {
   while (true) {
      Thread.sleep(500);
      if (c.hasChanged())
          Dispatcher.Invoke((Action)delegate() {updateData();});
   }

}).Start();

In 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();

There may be missing parameters to Invoke (which is needed to execute the code on the calling UI thread) but I'm writing this from my brain so no intellisense at disposal :D

In .NET 4 you can use TaskFactory.StartNew instead of spawning a thread by yourself.
In .Net <= 4, you could use the TreadPool for the thread.
However I recall you need this to be run at once because you expect it to be there checking as soon as possible and the thread pool won't assure you that (it could be already full, but not very likely:-).
Just don't do silly things like spawning more of them in a loop!

And inside the thread you should put a check like

while (!Closing)

so that the thread can finish when you need it without having to resort to bad things like t.Abort();
An when exiting put the Closing to true and do a t.Join() to close the checker thread.

EDIT:

I forgot to say that the Closing should be a bool property or a VOLATILE boolean, not a simple boolean, because you won't be ensured that the thread could ever finish (well it would in case you are closing the application, but it is good practice to make them finish by your will). the volatile keyword is intended to prevent the (pseudo)compiler from applying any optimizations on the code that assume values of variables cannot change

悸初 2024-11-11 02:23:35

从您的帖子中不清楚您想要做什么,但听起来您应该将模型/服务调用放在单独的线程上(通过后台工作人员或异步委托),并使用模型/服务调用的回调来通知完成后的 UI。然后,您的 UI 线程可以执行繁忙的操作,例如显示进度条,但不会变得无响应。

It's not clear from your post exactly what you are trying to do, but it sounds like you should put your model/service calls on a separate thread (via Background worker or async delegate) and use a callback from the model/service call to notify the UI when it's done. Your UI thread can then do busy things, like show a progress bar, but not become unresponsive.

烟柳画桥 2024-11-11 02:23:35

如果您从 GUI 进行轮询,请使用 (WinForms) 计时器。

如果这是某种后台进程,那么您的 Sleep() 可能是较小的危害。

If you are polling from a GUI, use a (WinForms) Timer.

If this is some kind of background process, your Sleep() may be the lesser evil.

感情旳空白 2024-11-11 02:23:35

显式的忙等待是邪恶的,必须尽可能避免。

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

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

Explicit busy waiting is evil and must be avoided whenever possible.

If you cannot avoid it, then build your application using the Observer design pattern and register the interested objects to an object which performs the polling, backed by a thread.

That way you have a clean design, confining the ugly stuff in just one place.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文