线程并未真正休眠?

3
我试图在用户点击 Enter 后禁用 TextBox 几秒钟:
<StackPanel>
    <TextBox x:Name="txt1" Width="150" Margin="10" KeyUp="txt1_KeyUp"/>
</StackPanel>   

private void txt1_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            txt1.IsEnabled = false;
            Thread.Sleep(2500);
            txt1.IsEnabled = true; //all text is added here
        }
    }

如果我在Thread睡眠时继续输入,当Thread“醒来”时,我键入的所有内容都会在TextBox中弹出。
我的问题是,如果GUI线程睡眠时是否有一种缓冲区存储所有已触发的事件?

6
不应该在UI线程上进行睡眠。相反,应禁用文本框并安排一个任务稍后重新启用它。 - Nick
我意识到让UI线程休眠不是正确的选择,但我的问题更多地涉及 Thread.Sleep 方法的工作原理。 - Yoav
1
你正在使UI线程休眠,因此输入的文本的关键事件需要等待。此外,在这2.5秒内,您可能会发现UI无响应,例如按Enter键然后尝试调整窗口大小。回答您的问题,它们不是缓冲的,但它们将被阻塞,因为它们都在一个线程上运行,而您已经停止了该线程的执行。 - TheKingDave
@TheKingDave 所有事件都在“等待”,直到线程唤醒,然后才被应用于应用程序? - Yoav
2
Windows中的UI本质上是单线程的,并使用消息泵工作。消息被添加到泵的队列中并使用UI线程进行处理。如果阻塞了该线程,则它无法处理消息,直到再次唤醒它。 - Nick
@Yoav,请查看Nick的回复,它们已经“排队”了。如果您查看我的答案,您会发现对您正在进行的方式进行微小更改将使您的用户界面更加响应。 - TheKingDave
1个回答

1
这里有一个更好的解决方案:
<StackPanel>
    <TextBox x:Name="txt1" Width="150" Margin="10" KeyUp="txt1_KeyUp"/>
</StackPanel>   

private void txt1_KeyUp(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter)
    {
        txt1.IsEnabled = false;
        Thread t = new Thread(() =>
        {
            System.Threading.Thread.Sleep(2500);
            Action action = () => txt1.IsEnabled = true;
            Dispatcher.Invoke(action);
        });
        t.Start();
    }
}

当您按下回车键时,您会发现该框被禁用,并且您不会在UI线程上睡眠。
如果您希望其他UI元素知道何时完成此操作,可以将t(线程)保存到表单中,并查询其状态(t.ThreadState)以确定是否已完成。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接