使用RichTextBox在文本追加中创建延迟

本文关键字:创建 延迟 追加 文本 RichTextBox 使用 | 更新日期: 2023-09-27 18:00:33

我正试图用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);,但这基本上冻结了线程!所以它一次粘贴所有内容,只是之前的延迟粘贴的蒙太奇!

我如何才能像我所描述的那样实现平滑延迟类型的系统?

使用RichTextBox在文本追加中创建延迟

您应该避免忙于等待,而是使用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),并且必须确保对所有影响UI的代码正确使用BeginInvoke。它甚至可能比async稍快。然而,线程有相当大的开销(主要是在内存方面),因此该解决方案不会扩展到大量延迟的交互。

摘要

  • 如果可以,请使用async
  • 或者,使用windows窗体Timer,这很麻烦
  • 或者使用后台线程,但要注意缩放问题和繁忙的等待

我通过这种方法解决了这个问题:暂停方法的执行而不锁定GUI。C#

它可以通过在单独的线程上运行暂停来轻松修复,因此不会锁定UI。感谢大家的帮助!