I want to put my program to a sleep for a couple of seconds. When i use thread.sleep(x) entire program doesn't respond. According to this article -> http://msdn.microsoft.com/en-us/library/hh184840(v=VS.92).aspx application which is not responsible for 3 seconds doesn't pass the certification :/ (i have to wait 5 seconds). Does anybody know a solution for this problem?
问题:
回答1:
You need to rethink what you are trying to do with your pause. It's a bit hard to say given that we don't have much info about what you try to achieve with this pause, but I'll give an example here to illustrate how you can get the wanted effect without having to pause the entire app (which you should never do).
Say you want to download file A, then wait 5 sec ,then download file B. You do this by running something like this:
var file = downloadFileA();
new Thread((ThreadStart)delegate
{
Thread.Sleep(5000);
downloadFileB();
});
Also, it's prefferable to make the actual download-calls async (if it is downloading you are doing), just to make sure that you don't feeze the GUI.
Alternativly, you can do both the downloads in the background-thread like this:
new Thread((ThreadStart)delegate
{
var file = downloadFileA();
Thread.Sleep(5000);
downloadFileB();
});
回答2:
Don't sleep the main thread of your application. Instead, do whatever you need to do that requires waiting in a background thread of your application.
If you put a Thread.Sleep() call in the main thread of your application, the app will become unresponsive to the UI message loop behind the scenes, as you see. This is because you're blocking execution while handling one message (the UI event that triggered the wait), so no other messages for the app can be handled.
Instead, structure this code to run asynchronously. I'm guessing there's some method that contains most of the heavy lifting including the sleep. As long as that's not an event handler (refactor it if it is) you can set up a second thread to run this method, and add a "callback" method that the method will call when it finishes, which will update the UI with the results. It's a little more work, but it keeps the app responsive, and it's generally good practice especially on multicore devices (even phones are getting dual-core CPUs nowadays). There are many ways to set up multithreaded operations. Delegate.BeginInvoke is my favorite:
public delegate void BackgroundMethod()
public void HandleUITrigger(object sender, EventArgs e)
{
//we'll assume the user does something to trigger this wait.
//set up a BackgroundMethod delegate to do our time-intensive task
BackgroundMethod method = DoHeavyLifting;
//The Delegate.BeginInvoke method schedules the delegate to run on
//a thread from the CLR's ThreadPool, and handles the callback.
method.BeginInvoke(HeavyLiftingFinished, null);
//The previous method doesn't block the thread; the main thread will move on
//to the next message from the OS, keeping the app responsive.
}
public void DoHeavyLifting()
{
//Do something incredibly time-intensive
Thread.Sleep(5000);
//Notice we don't have to know that we're being run in another thread,
//EXCEPT this method cannot update the UI directly; to update the UI
//we must call Control.Invoke() or call a method that Invokes itself
ThreadSafeUIUpdate();
}
public void ThreadSafeUIUpdate()
{
//A simple, thread-safe way to make sure that "cross-threading" the UI
//does not occur. The method re-invokes itself on the main thread if necessary
if(InvokeRequired)
{
this.Invoke((MethodInvoker)ThreadSafeUIUpdate);
return;
}
//Do all your UI updating here.
}
public void HeavyLiftingFinished()
{
//This method is called on the main thread when the thread that ran
//DoHeavyLifting is finished. You can call EndInvoke here to get
//any return values, and/or clean up afterward.
}
回答3:
Disclaimer: Thread.Sleep(n)
anywhere is pretty much a "code smell", meaning it's an indicator that other code in the app is going to be a problem as well. I generally avoid using it at all (I have never encountered a scenario where Thread.Sleep
must be used).
In your case, however, a simple drop-in replacement for Thread.Sleep(5000)
might be to just do this:
for (int i = 0; i < 10; i++) {
Thread.Sleep(500);
}
You'll achieve an overall wait time of 5 seconds, but the UI will never be locked for more than half a second.
回答4:
Looks like a job for ThreadPool.QueueUserWorkItem