如何在不使用睡眠的情况下在 C# 中执行短暂的延迟?

Posted

技术标签:

【中文标题】如何在不使用睡眠的情况下在 C# 中执行短暂的延迟?【英文标题】:How can I perform a short delay in C# without using sleep? 【发布时间】:2013-08-24 16:56:58 【问题描述】:

我对编程非常陌生,我认为到目前为止我的学习已经足够好,但我仍然无法理解以我想要的方式进行延迟的想法。我正在做的是一种使用涉及战斗系统的 Windows 窗体应用程序的测试“游戏”。在其中,我想制作一个每隔几秒钟执行一次动作的 NPC。问题是,我还想让玩家在攻击之间进行交互。 Thread.sleep 似乎真的不适合我,不仅因为我不知道如何多线程,而且每当我尝试运行它时,比如这样:

 textBox1.Text += "\r\nThread Sleeps!";
 System.Threading.Thread.Sleep(4000);
 textBox1.Text += "\r\nThread awakens!";

它似乎坚持先睡,然后打印两行。

我想这就是我目前能说的全部内容,但如果这仍然过于模糊或冗长,请随时告诉我。

简而言之,在 C# 中,我想在运行前做一些延迟,但同时仍然允许用户交互。

【问题讨论】:

您可以改用计时器并在您的时间间隔触发它... 线程还负责打印您的 UI,但由于您使用 Sleep 阻止它,它无法更新显示您的第一行的 UI。 使用 Task.Delay 代替睡眠。这样你就不会遇到被阻止的 UI 的任何问题。这个新功能在 .Net 4.5 中可用。 他/她问 - 没有睡觉:) 【参考方案1】:

您可能可以使用计时器:http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx

计时器可以为您提供高达 1 毫秒的精度。根据滴答间隔,将生成一个事件。在 tick 事件中做你的事情。

【讨论】:

【参考方案2】:

如果您使用的是 .NET 4.5,您可以使用新的 async/await 框架来休眠,而无需锁定线程。

它的工作原理是使用 async 关键字标记需要异步操作的函数。这只是对编译器的提示。然后在您希望代码异步运行的行上使用 await 关键字,您的程序将等待而不锁定线程或 UI。您调用的方法(在 await 行上)也必须用 async 关键字标记,并且通常以 Async 结尾,如 ImportFilesAsync 中所示。

在你的例子中你需要做的是:

    确保您的程序将 .Net Framework 4.5 作为目标框架 使用 async 关键字标记需要休眠的函数(参见下面的示例) 将using System.Threading.Tasks; 添加到您的代码中。

您的代码现在可以使用Task.Delay 方法而不是System.Threading.Thread.Sleep 方法(可以在Task.Delay 上使用await,因为Task.Delay 在其定义中标有async)。

private async void button1_Click(object sender, EventArgs e)

    textBox1.Text += "\r\nThread Sleeps!";
    await Task.Delay(3000);
    textBox1.Text += "\r\nThread awakens!";

您可以在此处阅读有关Task.Delay 和Await 的更多信息。

【讨论】:

await 之后的所有代码都将异步运行是否正确?我用两个复选框做了一个例子,似乎是这样。 @Black 您只能在标记为async 的函数上使用await,所以是的 - 它始终是异步的。 但只有等待之后的部分? @Black 是的,只有 await 关键字后面的部分【参考方案3】:

很抱歉唤醒了这样一个老问题。 但我认为原作者想要的答案是:

您需要在对 textbox1 进行更改后强制您的程序进行图形更新。你可以通过调用Update();来做到这一点

textBox1.Text += "\r\nThread Sleeps!";
textBox1.Update();
System.Threading.Thread.Sleep(4000);
textBox1.Text += "\r\nThread awakens!";
textBox1.Update();

通常这将在线程完成时自动完成。 例如,您按下一个按钮,对文本进行更改,线程终止,然后.Update() 被触发,您会看到更改。 (我不是专家,所以我不能真正告诉你它是什么时候被解雇的,但无论如何它都与此类似。)

在这种情况下,您进行更改,暂停线程,然后再次更改文本,当线程最终终止时,.Update() 被触发。这导致您只能看到对文本所做的最后一次更改。

如果在文本更改之间执行很长时间,您会遇到同样的问题。

【讨论】:

【参考方案4】:
private void WaitNSeconds(int seconds)

    if (seconds < 1) return;
    DateTime _desired = DateTime.Now.AddSeconds(seconds);
    while (DateTime.Now < _desired) 
         Thread.Sleep(1);
         System.Windows.Forms.Application.DoEvents();
    

【讨论】:

让 CPU 发疯并完全冻结整个线程的好方法。【参考方案5】:

通过将using System.Timers; 添加到您的程序中,您可以使用此功能:

private static void delay(int Time_delay)

   int i=0;
  //  ameTir = new System.Timers.Timer();
    _delayTimer = new System.Timers.Timer();
    _delayTimer.Interval = Time_delay;
    _delayTimer.AutoReset = false; //so that it only calls the method once
    _delayTimer.Elapsed += (s, args) => i = 1;
    _delayTimer.Start();
    while (i == 0)  ;

延迟是一个函数,可以像这样使用:

delay(5000);

【讨论】:

任何使用此代码的人,请注意:***.com/a/42863215/9691426

以上是关于如何在不使用睡眠的情况下在 C# 中执行短暂的延迟?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 VBA 的情况下在 Excel 中执行反向字符串搜索?

如何在不使用完成块的情况下在动画后执行代码?

如何在不脱离控制台的情况下在 Windows 中的 Python 中执行 os.execv()?

如何在不冻结 GUI 的情况下在单个插槽中实现阻塞进程?

如何在不导入所有函数的情况下在包中使用 data.table?

如何在不使用count(*)的情况下在greenplum中查找表中的行数