使用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);
,但这基本上冻结了线程!所以它一次粘贴所有内容,只是之前的延迟粘贴的蒙太奇!
我如何才能像我所描述的那样实现平滑延迟类型的系统?
您应该避免忙于等待,而是使用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。感谢大家的帮助!