在文本中创建延迟附加RichTextBox

时间:2013-02-21 09:29:33

标签: c# richtextbox delay

我正在尝试使用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);一样调用它,但这基本上冻结了线程!所以它无论如何都会立刻粘贴,只是延迟了 贴的蒙太奇!

如何像我所描述的那样进行平滑延迟型系统?

2 个答案:

答案 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线程的情况下,你会留在它上面;这很重要,因为只有那个线程可能会改变你的文本框。

总结一下你想要这样做的原因如下:

  • 你可以避免CPU忙碌等待浪费精力。
  • 您可以避免阻止GUI线程,以便您的更新按时出现(与CPU占用不同,例如与Thread.Sleep不同)
  • 您不需要特别担心线程调度,因为异步功能会为您执行此操作。

如果您需要支持.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。谢谢大家的帮助!