Thread.Sleep(300) not working correctly

允我心安 提交于 2019-12-24 12:19:39

问题


I want it to execute the first part of the code, then make the pictureBox visible, pause for 3 seconds, hide the pictureBox and execute the rest of the code:

// first part of the code here
pb_elvisSherlock.Visible = true;
Thread.Sleep(300);
pb_elvisSherlock.Visible = false;
// rest of the code here

But it executes the whole block of code and only then pauses. Any ideas what to do?

Thanks!


回答1:


pb_elvisSherlock.Visible = true;
Application.DoEvents(); //let the app show the picturebox
Thread.Sleep(3000);
pb_elvisSherlock.Visible = false;

The problem is that you don't give the message loop a chance to display the picture box before you pause the GUI thread. Application.DoEvents() solve that.

Note that using Thread.Sleep on the GUI thread will make the painting freeze (try move a window over your app when the Sleep is active).

You should do something like this:

pb_elvisSherlock.Visible = true;
int counter = 0;
while (counter < 30)
{
  Application.DoEvents(); 
  Thread.Sleep(100);
  ++counter;
}
pb_elvisSherlock.Visible = false;

It's still kind of a hack but the window will be redrawn and respond as it should.

Update 2

Well. DoEvents seems to be a bit to much of a hack. (thanks for the comments).

If the picturebox is a kind of a nag screen do something like this:

Alternative 1

  1. Create a new form containing only the picturebox (don't use a border on that form).
  2. Add a timer to that form that calls Close after three seconds
  3. Call 'myNagForm.DoModal()'

That solution prevents your users from doing anything in your "normal" form while the nagform is visible.

Alternative 2

  1. Create a background worker, see here for example: http://dotnetperls.com/backgroundworker
  2. Move your picturebox AND the code executed after it to the background worker method.



回答2:


If you are trying to make a PictureBox appear for 3 seconds, you probably want your application to remain responsive during this time. So using Thread.Sleep is not a good idea because your GUI thread does not process messages while sleeping.

A better alternative would be to set a System.Windows.Forms.Timer for 3000 ms, to hide the PictureBox after 3 seconds without blocking your GUI.

For example, like this:

pb.Visible = true;
var timer = new Timer();
timer.Tick += () => { pb.Visible = false; timer.Stop(); };
timer.Interval = 3000;
timer.Start();



回答3:


The problem is that you are blocking the UI thread, which is the thread responsible for doing the redrawing of your form, so nothing gets redrawen during the 3 seconds you are waiting (Try draging your form around during these 3 seconds and you'll see it's totally unresponsive).

There are loads of ways of dealing with this, but the basic premise is that firstly you need to do your waiting on a background thread so your UI thread remains responsive (Options include using a BackgroundWorker, a Timer, the ThreadPool, a Thread or the TPL TaskFactory). Secondly, you must remember that any update to the UI must be done on the UI thread, so you must switch back to your UI thread (Using .Invoke() or a TaskScheduler) before you hide the picture box at the end.

This example uses the TPL (Task Parallel Library):

// Start by making it visible, this can be done on the UI thread.
pb_elvisSherlock.Visible = true;

// Now grab the task scheduler from the UI thread.
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

// Now create a task that runs on a background thread to wait for 3 seconds.
Task.Factory.StartNew(() =>
{
    Thread.Sleep(3000);

// Then, when this task is completed, we continue...
}).ContinueWith((t) =>
{
    //... and hide your picture box.
    pb_elvisSherlock.Visible = false;

// By passing in the UI scheduler we got at the beginning, this hiding is done back on the UI thread.
}, uiScheduler);



回答4:


First of all you are only sleeping for 300 milliseconds not 3 seconds

Thread.Sleep(3000);

Second your User interface will first be updated when your code is done executing, so you need to do something like this




回答5:


I would try making this longer:

Thread.Sleep(300);

change to

Thread.Sleep(3000);

You are only pausing for .3 seconds in your example (3000 = 3 seconds). If I had to guess, you aren't waiting long enough for the window to display. The code is actually working correctly.

Like the comment try adding in Application.DoEvents(); after setting the visibility property.




回答6:


Extensions are quite helpful in such situations ;-)

public static class IntExtensions
{
    public static TimeSpan Seconds(this int value)
    {
        return new TimeSpan(0, 0, value);
    }
}

Thread.Sleep(3.Seconds());



回答7:


You can try this Task.Delay(TimeSpan.FromSeconds(3)).Wait(); wherever Thread.Sleep method sometimes doesn't block the thread.



来源:https://stackoverflow.com/questions/4510397/thread-sleep300-not-working-correctly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!