运行程序时等待一秒钟

179
dataGridView1.Rows[x1].Cells[y1].Style.BackColor = System.Drawing.Color.Red;
System.Threading.Thread.Sleep(1000);

我想在打印格子之前等待一秒钟,但这段代码没有生效。我该怎么做?


1
在等待1秒钟后,应该运行哪些代码? - Allensb
1
你怎么知道它不工作?试试 sleep 10000 然后看看它是否工作。1000 太短了,无法评估它是否工作。 - Missy
这个很好用:System.Threading.Thread.Sleep(1000); - Andrew
12个回答

276

它是否暂停了,但您没有看到单元格中出现红色?尝试这个:

dataGridView1.Rows[x1].Cells[y1].Style.BackColor = System.Drawing.Color.Red;
dataGridView1.Refresh();
System.Threading.Thread.Sleep(1000);

51

个人认为Thread.Sleep是一种较差的实现方式,会锁定用户界面等。我个人喜欢计时器实现,因为它能够等待并触发事件。

用法:DelayFactory.DelayAction(500, new Action(() => { this.RunAction(); }));

//Note Forms.Timer and Timer() have similar implementations. 

public static void DelayAction(int millisecond, Action action)
{
    var timer = new DispatcherTimer();
    timer.Tick += delegate

    {
        action.Invoke();
        timer.Stop();
    };

    timer.Interval = TimeSpan.FromMilliseconds(millisecond);
    timer.Start();
}

3
什么是DispatcherTimer?我无法在Winform项目中包含它。 - Meric Ozcan
感谢提供的有用信息和代码。 - undefined

34

使用定时器的等待函数,没有UI锁定。

public void wait(int milliseconds)
{
    var timer1 = new System.Windows.Forms.Timer();
    if (milliseconds == 0 || milliseconds < 0) return;

    // Console.WriteLine("start wait timer");
    timer1.Interval = milliseconds;
    timer1.Enabled  = true;
    timer1.Start();

    timer1.Tick += (s, e) =>
    {
        timer1.Enabled = false;
        timer1.Stop();
        // Console.WriteLine("stop wait timer");
    };

    while (timer1.Enabled)
    {
        Application.DoEvents();
    }
}

用法:将这段代码放入需要等待的代码中即可:

wait(1000); //wait one second

只是一个建议。如果你将min乘以60000,参数名称会更有意义。timer1.Interval = min * 60000; - Golda
1
是的,你说得对,应该是毫秒而不是分钟。我会更新名称。谢谢。 - Said

29

看起来.Net Core缺少DispatcherTimer

如果我们可以使用异步方法,Task.Delay将满足我们的需求。 如果您想因限速原因在for循环中等待,这也可能非常有用。

public async Task DoTasks(List<Items> items)
{
    foreach (var item in items)
    {
        await Task.Delay(2 * 1000);
        DoWork(item);
    }
}

你可以按照以下方式等待该方法的完成:

public async void TaskCaller(List<Item> items)
{
    await DoTasks(items);
}

那就是完美的方式。谢谢! :) - Deniz

10

最佳的等待方式是使用 Task.Delay 函数来避免阻塞主线程。

因此,您的代码将如下所示:

var t = Task.Run(async delegate
{              
    dataGridView1.Rows[x1].Cells[y1].Style.BackColor = System.Drawing.Color.Red;
    dataGridView1.Refresh();
    await Task.Delay(1000);             
});

这有可能会让读者感到困惑。原始问题并没有指定他们的打印代码,而你假设它应该在dataGridView1代码之后运行。我建议在Task.Delay之后添加一些额外的注释,以表明等待是在那里完成的。此外,整个结构不会阻塞,因此不熟悉Task.Run的用户可能会认为Task.Run命令本身会等待(但实际上不会)。 - Andreas Pardeike
嘿,感谢您的输入,但我不认为我完全明白您想让我做什么,如果您可以编辑此答案,那将非常棒! - amitklein

7

我觉得这里的问题只是顺序有误,Selçuklu想让应用在填充网格之前等待一秒钟,因此Sleep命令应该在填充命令之前。

    System.Threading.Thread.Sleep(1000);
    dataGridView1.Rows[x1].Cells[y1].Style.BackColor = System.Drawing.Color.Red;

5

如果使用异步

await Task.Delay(new TimeSpan(0, 0, 1));

否则

Thread.Sleep(new TimeSpan(0, 0, 1));

3

如果忙等待时间很短,那么它不会成为一个严重的缺点。在我的案例中,需要通过闪烁控件来向用户提供视觉反馈(这是一个图表控件,可以复制到剪贴板,在某些毫秒内更改其背景)。这种方法效果很好:

using System.Threading;
...
Clipboard.SetImage(bm);   // some code
distribution_chart.BackColor = Color.Gray;
Application.DoEvents();   // ensure repaint, may be not needed
Thread.Sleep(50);
distribution_chart.BackColor = Color.OldLace;
....

1
使用 dataGridView1.Refresh(); :)

1
这个解决方案很简短,据我所知,也很轻便易行。
public void safeWait(int milliseconds)
{
    long tickStop = Environment.TickCount + milliseconds;
    while (Environment.TickCount < tickStop)
    {
        Application.DoEvents();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接