如何在不使用睡眠的情况下在 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()?