Thread.Sleep(300)无法正常工作

时间:2010-12-22 14:54:25

标签: c# winforms multithreading sleep

我希望它执行代码的第一部分,然后使pictureBox可见,暂停3秒,隐藏pictureBox并执行其余代码:

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

但它会执行整个代码块,然后才会暂停。任何想法该怎么做?

谢谢!

7 个答案:

答案 0 :(得分:11)

如果您尝试使PictureBox显示3秒钟,您可能希望应用程序在此期间保持响应。所以使用Thread.Sleep不是一个好主意,因为你的GUI线程在睡觉时不会处理消息。

更好的选择是将System.Windows.Forms.Timer设置为3000毫秒,在3秒后隐藏PictureBox而不会阻止您的GUI。

例如,像这样:

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

答案 1 :(得分:5)

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

问题是,在暂停GUI线程之前,不要给消息循环提供显示图片框的机会。 Application.DoEvents()解决了这个问题。

请注意,使用Thread.Sleep GUI线程上会使绘画冻结(尝试通过应用程式移动窗口时,Sleep是激活的)。

你应该这样做:

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

它仍然是一种黑客攻击,但窗口将重新绘制并按原样响应。

更新2

好。 DoEvents似乎有点像黑客。 (感谢评论)。

如果图片框是一种唠叨屏幕,请执行以下操作:

备选方案1

  1. 创建仅包含图片框的新表单(不要在该表单上使用边框)。
  2. 在三秒钟后调用Close的表单中添加一个计时器
  3. 调用'myNagForm.DoModal()'
  4. 该解决方案可以防止您的用户以“正常”形式执行任何操作,同时可以看到nagform。

    备选方案2

    1. 创建后台工作者,请参阅此处:http://dotnetperls.com/backgroundworker
    2. 将您的图片框及其后执行的代码移动到后台工作程序方法。

答案 2 :(得分:3)

问题是你正在阻止UI线程,这是负责重新绘制表单的线程,因此在你等待的3秒内没有任何东西被重绘(尝试在这3秒内拖动你的表单并且你会发现它完全没有反应。)

有很多方法可以解决这个问题,但基本的前提是首先需要在后台线程上等待,以便你的UI线程保持响应(选项包括使用BackgroundWorker,{{ 3}},TimerThreadPoolThread TPL)。其次,您必须记住,UI的任何更新都必须在UI线程上完成,因此您必须切换回UI线程(使用TaskFactory.Invoke()),然后再隐藏图片框结束。

此示例使用TPL(任务并行库):

// 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);

答案 3 :(得分:1)

我会尝试延长时间:

Thread.Sleep(300);

更改为

Thread.Sleep(3000);

您的示例中仅暂停.3秒(3000 = 3秒)。如果我不得不猜测,你没有等待足够长的时间来显示窗口。代码实际上正常工作。

与评论一样,请在设置可见性属性后添加Application.DoEvents();

答案 4 :(得分:1)

首先,你只睡了300毫秒而不是3秒

Thread.Sleep(3000);

当您的代码执行完毕后,您的用户界面将首先更新,因此您需要执行this

之类的操作

答案 5 :(得分:0)

在这种情况下,扩展非常有用; - )

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

Thread.Sleep(3.Seconds());

答案 6 :(得分:0)

无论Thread.Sleep方法有时不会阻塞线程,您都可以尝试使用此Task.Delay(TimeSpan.FromSeconds(3)).Wait();