C# 如何在运行时在代码块结束之前更改按钮的背景色

C# 如何在运行时在代码块结束之前更改按钮的背景色,c#,winforms,C#,Winforms,按钮1已经是暗绿色。当我点击按钮1时,没有任何变化 如何在5秒钟内观察此更改?此操作不起作用的原因是线程.Sleep阻止线程完成 仅当应用程序未执行任何操作时,即在方法完成后,才会重新绘制窗口。如果你移除将其更改为暗绿色的线条,你会看到它在五秒钟后改变颜色 你应该用定时器来解决你的问题 如果需要,可以强制它提前刷新接口,而不必通过调用Application.DoEvents离开该方法;这将反映你所做的改变,比如颜色的改变 public partial class Form1 : Form {

按钮1已经是暗绿色。当我点击按钮1时,没有任何变化


如何在5秒钟内观察此更改?

此操作不起作用的原因是线程.Sleep阻止线程完成

仅当应用程序未执行任何操作时,即在方法完成后,才会重新绘制窗口。如果你移除将其更改为暗绿色的线条,你会看到它在五秒钟后改变颜色

你应该用定时器来解决你的问题

如果需要,可以强制它提前刷新接口,而不必通过调用Application.DoEvents离开该方法;这将反映你所做的改变,比如颜色的改变

public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();
  }

  private void button1_Click(object sender, EventArgs e)
  {
    button1.BackColor = Color.Lime;
    Thread.Sleep(5000);
    button1.BackColor = Color.DarkGreen;
  }
}

请注意,在具有用户界面的程序中设置线程睡眠是一个坏主意,但为了便于演示,它将向您展示如何使其更改颜色。

我不建议使用Thread.Sleep,因为它将冻结您的界面。您还需要刷新按钮,以便显示更改。 您可以使用async和wait方法延迟按钮颜色更改 在button1\u click函数的private关键字后添加async 创建异步任务函数并删除线程。带有wait waiting的Sleep函数

    button1.BackColor = Color.Lime;
    Application.DoEvents()
    Thread.Sleep(5000);
    button1.BackColor = Color.DarkGreen;

您的问题是因为UI线程被阻止。您需要在单独的线程中运行此逻辑。请尝试以下代码:

public partial class Form1 : Form
{
    public Form1()
{
    InitializeComponent();
}

private async void button1_Click(object sender, EventArgs e)
{
    button1.BackColor = Color.Lime;
    button1.Refresh();
    await awaiting();

    button1.BackColor = Color.DarkGreen;
}
private async Task awaiting() {
        await Task.Delay(5000);
    }
}

这将把你的按钮变成灰绿色,然后等待5秒钟,再把它转回到暗绿色。这是因为我们正在一个新线程中旋转它,因此不会锁定UI。

wpf或winfrom?尝试插入一个按钮1。刷新;如果您使用的是winforms或MVC,那么使用Javascript可能会更好。你能更具体地说明你的问题吗?另外,你当前的代码会冻结界面,这不是我想象中你想要的。如果你想在几秒钟后更改按钮颜色,请创建按钮。单击处理程序异步私有异步无效按钮1\u单击对象发送者,事件参数e,设置第一种颜色,然后等待任务。延迟5000,然后设置第二种颜色。如果需要,首先禁用按钮,然后在metod返回之前再次启用。这不是最好的建议。OP的设计可能被认为是错误的。你可以改进这个答案,添加一些链接到更好的UI设计技巧。我可以,但这超出了问题的范围,看起来OP试图改变按钮颜色五秒钟,只是为了看看如何,并且无意中发现了表单应用程序的一个怪癖,它们只在线程不忙于做其他事情时更新。我已经解释了表单应用程序是如何工作的,为什么颜色变化测试不起作用,并且线程睡眠在表单应用程序中是个坏主意。我认为这应该足够了。据我所知,在代码块用完事件之前,问题就出现了。我们可以通过在代码块中调用Application.DoEvents来克服这个问题。谢谢您的帮助,您只需拨打button1.更新;要立即更新按钮,无需调用Application.DoEvents。您可能还想考虑在另一个答案中描述的Asic/Acess方法,它在不阻塞UI线程的情况下起到了作用。尽管学术界基本上是相同的,但更新只是强制互操作消息重绘窗口,application doevents告诉windows执行排队等待执行的所有操作,这些操作将包含相同的消息。是的,您应该使用async await来正确地执行此操作,但我不认为OP试图让按钮显示5秒钟,他们正在试图找出如何更改按钮的颜色。下面的异步示例也不好,因为您不应该直接从单独的线程访问控件。不需要执行任务。在这种情况下,请在异步方法中运行。在Task.Run中设置按钮的背景色时,您也从另一个线程访问UI元素。只要在异步方法中这样做就足够了:button1.BackColor=Color.LimeGreen;等待任务。延迟5000;button1.BackColor=Color.DarkGreen;这看起来不是线程安全的,在这种情况下可能有效,但这不是一个好的做法,如果要从单独的线程访问表单控件,则应使用BeginInvoke。无需调用button1.Refresh;因为UI线程没有被阻塞,在将颜色设置回石灰色后将重新绘制。
private async void button1_Click(object sender, EventArgs e)
{
    button1.BackColor = Color.LimeGreen;
    await Task.Run(() =>
    {
        System.Threading.Thread.Sleep(5000);
        button1.BackColor = Color.DarkGreen;
    });
}