我正在尝试使用C#创建一个逼真的控制台类型游戏,我需要它做的是附加这样的文字:
喜
你好
真棒
好的
但不是一次性全部,我希望它能做到这一点:
喜
(暂停2秒)
你好
(暂停4秒)
真棒
(暂停1秒)
好的
我试过这个:
delegate void _pause(int time);
void pause(int time)
{
if (txtInput.Text != "")
{
txtInput.Clear();
}
Stopwatch s = new Stopwatch();
s.Start();
while (s.Elapsed < TimeSpan.FromSeconds(time))
{
}
s.Stop();
return;
}
然后我可以像Invoke(new _pause(pause),3);
一样调用它,但这基本上冻结了线程!所以它无论如何都会立刻粘贴,只是延迟了
贴的蒙太奇!
如何像我所描述的那样进行平滑延迟型系统?
答案 0 :(得分:3)
您应该避免忙碌等待,而是使用Task.Delay
等计时器。
这样做的一种可能方法是利用C#4.5的新异步功能:
async void converse() {
txtInput.Text = "hi\n";
await Task.Delay(2000);
txtInput.Append("hello\n");
await Task.Delay(4000);
txtInput.Append("awesome\n");
await Task.Delay(1000);
txtInput.Append("nice\n");
}
通过使用异步语法,您指示计算机运行与其他代码交错的代码 - 例如,它仍然可以在此期间进行屏幕更新。它会自动返回到同一个SynchronizationContext,所以在你开始使用GUI线程的情况下,你会留在它上面;这很重要,因为只有那个线程可能会改变你的文本框。
总结一下你想要这样做的原因如下:
如果您需要支持.NET 2.0,您可能需要查看Windows窗体Timer
。简而言之,这会暴露事件处理程序,您可以在延迟后挂钩。但是,正如MSDN页面上的示例所示,它不那么容易使用,并且需要更多的手动编排。
此外,您可以使用线程。如果你这样做,你有责任确保线程安全:你不能在GUI线程以外的任何线程上执行txtInput.Append
:
void startConversation() {
(new Thread(converse) {IsBackground = true}).Start();
}
void converse() { //called a different thread
UI(() => txtInput.Text = "hi\n");
Thread.Sleep(2000);
UI(() => txtInput.Append("hello\n"));
Thread.Sleep(4000);
UI(() => txtInput.Append("awesome\n"));
Thread.Sleep(1000);
UI(() => txtInput.Append("nice\n"));
}
void UI(Action action) { this.BeginInvoke(action); }
这个模型几乎和异步模型一样简单。两个陷阱是你应该避免忙等待(使用Thread.Sleep)并且你必须确保正确使用BeginInvoke
来影响所有影响UI的代码。它甚至可能比async
略快。但是,线程的开销相当大(主要是内存方面),因此这种解决方案不会扩展到大量的延迟交互。
async
。Timer
,这很麻烦。答案 1 :(得分:0)
我通过这种方法解决了这个问题: Pause execution of a method without locking GUI. C#
可以通过在单独的线程上运行暂停来轻松修复,因此不会锁定UI。谢谢大家的帮助!