保持 UI 响应的 Thread.Sleep 替代方案?

发布于 2024-10-26 10:23:50 字数 343 浏览 4 评论 0原文

我在 Visual Studio 2008 中用 C# 完成所有这些工作。

我想放慢算法的工作速度,以便用户可以观看它的工作。 GUI 上会出现周期性变化,因此我在每个实例之后添加了 Thread.Sleep。

问题是,当设置为至少一秒时,在几次 Thread.Sleep 实例(几次循环后)之后,Thread.Sleep 只会冻结整个 GUI 并保持其状态直到程序完成。不是马上发生,但它总是会发生。多久取决于睡眠时间的长短。

我有证据表明整个程序不会冻结,它正在工作,甚至睡眠也会暂停正确的长度。但 GUI 在某个时刻冻结,直到算法结束,此时它显示正确的最终状态。

如何解决这个问题?在某个点暂停算法的替代方案?

I'm doing all this in C#, in Visual Studio 2008.

I want to slow down the work of my algorithm so that the user can watch it's work. There is a periodic change visible at the GUI so I added Thread.Sleep after every instance.

Problem is that Thread.Sleep, when set to at least a second, after a few instances of Thread.Sleep (after few loops) simply freezes entire GUI and keeps it that way till program completion. Not right away, but it always happens. How soon depends on the length of the sleep.

I have proof that entire program does not freeze, it's working it's thing, even the sleep is making pauses of correct length. But the GUI freezes at certain point until the algorithm ends, at which point it shows the correct final state.

How to solve this issue? Alternative to pausing algorithm at certain point?

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

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

发布评论

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

评论(4

蹲墙角沉默 2024-11-02 10:23:50

首先,不要让用户在考虑工作何时完成之前就等待工作完成。毫无意义。请直接说不。

其次,您正在“休眠”UI 线程。这就是 UI 线程“锁定”的原因。 UI线程不能被阻塞;如果是,UI 线程无法更新表单上的控件并响应系统消息。响应系统消息是UI线程的重要任务;如果不这样做,您的应用程序就会显得被系统锁定。不是什么好事。

如果您想完成此任务(请不要),只需创建一个 计时器 当你开始做工作时,当它 Ticks ,表示是时候停止假装工作了。

再次强调,请不要这样做。

First off, don't make the user wait for work that is done before they even think about when it will be finished. Its pointless. Please, just say no.

Second, you're "sleeping" the UI thread. That's why the UI thread is "locking up." The UI thread cannot be blocked; if it is, the UI thread cannot update controls on your forms and respond to system messages. Responding to system messages is an important task of the UI thread; failing to do so makes your application appear locked up to the System. Not a good thing.

If you want to accomplish this (please don't) just create a Timer when you start doing work that, when it Ticks, indicates its time to stop pretending to do work.

Again, please don't do this.

我还不会笑 2024-11-02 10:23:50

我猜一切都在一个线程中运行。用户可能通过单击按钮或类似按钮来调用该算法。这是由主线程的消息队列处理的。在此事件处理程序返回之前,您的应用程序的 GUI 无法更新。它需要定期抽取消息队列才能保持响应。

睡眠几乎从来都不是一个好主意,在 GUI 线程中也绝对不是一个好主意。我不会建议您继续使用睡眠并通过调用 Application.DoEvents 使 GUI 响应。

相反,您应该在后台线程中运行此算法,并且当它完成时,它应该向主线程发出信号。

I'd guess everything is running out of a single thread. The user probably invokes this algorithm by clicking on a button, or some such. This is handled by your main thread's message queue. Until this event handler returns, your app's GUI cannot update. It needs the message queue to be pumped on regular basis in order to stay responsive.

Sleeping is almost never a good idea, and definitely not a good idea in the GUI thread. I'm not going to recommend that you continue to use sleep and make your GUI responsive by calling Application.DoEvents.

Instead, you should run this algorithm in a background thread and when it completes it should signal so to the main thread.

家住魔仙堡 2024-11-02 10:23:50

您将要犯一些相当常见的用户界面错误:

  • 不要向用户发送垃圾邮件,她只对结果感兴趣
  • 不要强迫用户按照您的要求快速工作
  • 不要禁止用户与您的交互当你忙的时候计划。

相反:

  • 在列表框等小工具中显示结果,以允许用户按照自己的节奏查看结果
  • 通过使用线程保持用户界面交互 通过调试器
  • 减慢时间以实现您自己的利益

You are about to commit some fairly common user interface bloopers:

  • Don't spam the user with minutiae, she's only interested in the result
  • Don't force the user to work as fast as you demand
  • Don't forbid the user to interact with your program when you are busy.

Instead:

  • Display results in a gadget like a ListBox to allow the user to review results at her pace
  • Keep a user interface interactive by using threads
  • Slow down time for your own benefit with a debugger
泅渡 2024-11-02 10:23:50

这取决于很多事情,所以很难根据你所说的给出具体答案。不过,这里有一些可能相关的问题:

您是否在 UI 线程上执行此操作(例如触发工作开始的表单按钮或 UI 事件的线程)?如果是这样,最好创建一个新线程来执行该工作。

你为什么要睡觉?如果与正在进行的工作相关的状态可用于所有相关线程,那么观察者是否可以在工作线程休眠的情况下观察到这一点?也许工作线程可以将当前进度的指示器写入易失性或锁定变量(如果它大于指针大小(例如 int 或对象),则必须锁定它,但否则不能。如果未锁定,那么易失性将阻止缓存CPU 之间的不一致,尽管这可能不是什么大问题)。在这种情况下,您可以使用表单计时器(.Net 中有不同用途的不同计时器)检查该变量的状态并更新 UI 以反映正在完成的工作,而工作线程无需执行任何操作。最多有时它可能对工作线程中的 Yield() 有利,但即使这样也不太可能需要。

This depends on a lot of things, so its hard to give a concrete answer from what you've said. Still, here are some matters that might be relevant:

Are you doing this on a UI thread (e.g. the thread the form-button or UI event that triggered the work started on)? If so, it may be better to create a new thread to perform the work.

Why do you sleep at all? If the state related to the ongoing work is available to all relevant threads, can the observer not just observe this without the working thread sleeping? Perhaps the working thread could write an indicator of the current progress to a volatile or locked variable (it must be locked if it's larger than pointer size - e.g. int or an object - but not otherwise. If not locked, then being volatile will prevent cache inconsistency between CPUs, though this may not be a big deal). In this case you could have a forms timer (there are different timers in .Net with different purposes) check the status of that variable and update the UI to reflect the work being done, without the working thread needing to do anything. At most it may be beneficial to Yield() in the working thread on occasion, but its not likely that even this will be needed.

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