C# - Alternative to Thread.Sleep?

2019-03-05 10:13发布

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 atleast 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 happends. 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?

4条回答
祖国的老花朵
2楼-- · 2019-03-05 10:29

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.

查看更多
何必那么认真
3楼-- · 2019-03-05 10:38

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.

查看更多
小情绪 Triste *
4楼-- · 2019-03-05 10:44

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
查看更多
ら.Afraid
5楼-- · 2019-03-05 10:52

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.

查看更多
登录 后发表回答