C# 按钮 - 多个方法调用

本文关键字:方法 调用 按钮 | 更新日期: 2023-09-27 18:22:21

一个基本的C#问题。

我的表单上有两个禁用的文本框和一个按钮。该按钮当前如下所示:

    private void start_Click(object sender, EventArgs e)
    {
        this.two();
        this.hold();
        this.one()
    }

如您所见,它调用了其他三种方法,如下所示:

  • "two" - 使两个文本框都为背景色、黑色。
  • "一" - 只制作其中一个框 背景颜色 黑色。
  • "拿">
    • 调用"System.Threading.Thread.Sleep(1000(;"以暂停程序一秒钟。
    • 将两个文本框的背景色更改回白色。

我遇到的问题是程序似乎跳过了第一个调用到两个。只需按住程序一秒钟,然后将一个文本框更改为黑色。

感谢您的任何帮助!

C# 按钮 - 多个方法调用

您可能遇到的是,您在应用程序的主线程上运行此代码,该线程还负责响应 Windows GUI 消息(如更改文本框颜色后重新绘制自身的命令(。程序当前不会处理此消息,直到此事件处理程序完全执行后,此时只有一个文本框是黑色的。

如前所述,Application.DoEvents(( 将通过中断此处理程序并允许程序在继续之前处理来自 GUI 的排队消息来解决问题。执行此操作的另一种方法是在 BackgroundWorker 中运行此代码,该线程将使用单独的处理线程来告诉 GUI 线程重新着色文本框,同时不使用 Sleep(( 命令阻止 GUI 线程。通常,使用多线程方法更好,因为 Application.DoEvents(( 可能会在当前事件处理程序尚未完成时强制调用其他事件处理程序,从而导致意外后果(例如,对引发异常的另一个事件处理程序的调用将通过您中断的那个 Application.DoEvents 调用抛出,这实际上没有问题(。

正如其他人提到的,这是因为您的 UI 线程在开始刷新显示之前开始休眠。

切勿在 UI 线程上调用Thread.Sleep。它会"阻止"你的程序并激怒你的用户。如果你有一些需要Thread.Sleep的工作要做,创建一个新线程,但不要在 UI 线程中执行此操作。

它不会跳过对two的调用,但由于您通过调用Thread.Sleep来阻止 UI 线程,因此 UI 永远不会有机会刷新以显示two的效果。

你可以做这样的事情:

private void start_Click(object sender, EventArgs e)
{
    this.two()
    Task.Factory.StartNew(() => this.hold())
                .ContinueWith(_ => this.one(), TaskScheduler.FromCurrentSynchronizationContext());
}

它将在新线程中执行hold(因此不会冻结 UI(,然后在hold完成后,它将在 UI 线程上执行two

试试这个:

private void start_Click(object sender, EventArgs e)
{
    this.two();
    Application.DoEvents();
    this.hold();
    this.one();
}

调用 DoEvents(); 允许窗口在单击处理程序的中间重新绘制,而不是等到完成。

编辑:请阅读对此答案的评论...您会发现执行这样的阻止操作是"不好的做法"。

由于您在 UI 线程上执行Thread.Sleep,因此您的表单没有机会更新自身并使用新颜色重新绘制。

您可以在hold之前引入Application.DoEvents调用;但是,正如其他人指出的那样,这将导致您的UI线程在一秒钟的延迟内保持冻结状态(并且对用户活动无响应(。

在逻辑中引入延迟的最佳方法是使用 Timer 。下面是一些在延迟一秒后two执行的示例代码。

Timer timer = new Timer { Interval = 1000 };
timer.Tick += (sender, e) =>
{
    this.Invoke(new Action(two));
    timer.Stop();
    timer.Dispose();
};
timer.Start();