【问题标题】:Wait before changing a Control's text after previous change [duplicate]在先前更改后更改控件的文本之前等待[重复]
【发布时间】:2021-07-28 09:14:56
【问题描述】:

我希望标签的文本在按下按钮后随其颜色一起改变。
第一部分旨在将TextForeColor 更改为Color.Orange,然后等待1 秒钟,然后再次更改Text 属性并将ForeColor 设置为Color.LightGreen

我的问题是它没有按顺序执行,它只是跳过第一部分并更改为第二部分(文本变为“完成!”,颜色变为浅绿色)。

这是我的代码:

private void button1_Click(object sender, EventArgs e)
{
    label6.Text = "Working..";
    label6.ForeColor = Color.Orange;

    System.Threading.Thread.Sleep(1000);
    label6.Text = "Finsihed!";
    label6.ForeColor = Color.LightGreen;
}

【问题讨论】:

  • 不要在 UI 线程中使用 Sleep。主要是因为它会阻止用户交互的形式,你所体验的只是使用它的另一种效果。 delay something 还有其他方法:最推荐使用Timerasync/await(其他形式的多线程中最好的)。

标签: c# .net winforms


【解决方案1】:

你需要告诉你的标签在你睡觉之前更新

private void button1_Click(object sender, EventArgs e)
{
    label6.Text = "Working..";
    label6.ForeColor = Color.Orange;
    label6.Update(); // tell the label to update now

    System.Threading.Thread.Sleep(1000);
    label6.Text = "Finished!";
    label6.ForeColor = Color.LightGreen;
    label6.Update(); // tell the label to update now
}

但是还有另一种方法可以做到这一点。当您在 click 方法中使用 async 并使用 Task.Delay() 而不是 Thread.Sleep() 时,无需调用 Update() 语句。
这也使您的表单保持响应。

这是一个示例,说明如何在您的情况下执行此操作。

private async void button1_Click(object sender, EventArgs e)
{
    label6.Text = "Working..";
    label6.ForeColor = Color.Orange;

    await System.Threading.Tasks.Task.Delay(1000);
    label6.Text = "Finished!";
    label6.ForeColor = Color.LightGreen;
}

那么,Update()async 哪个更好?
那要看情况了

当您将UpdateThread.Sleep() 一起使用时,您的表单将根据需要进行更新。但在您的 Thread.Sleep() 完成之前,它也不会响应任何内容。
这可能是件坏事,但也可能是件好事。
这取决于你的情况。在Thread.Sleep() 完成之前,您可能不希望用户能够做任何事情。但这也意味着用户不能将表单拖动到其他位置。这对用户来说可能很烦人。

当您使用asyncTask.Delay() 时,您的表单也会根据需要更新。但它也会响应其他操作,例如拖动、调整大小、单击等...
如果你想要这个,那么这就是要走的路。
如果你不想要这个,那么要么再次使用Update(),要么确保用户不能点击任何他不应该点击的东西。
后者是一个很好的解决方案,因为用户仍然可以将表单拖动到他想要的位置,因为操作正在运行,但仍然不会做错任何事情。
这意味着在您开始操作之前,禁用他应该无法单击的所有控件,然后开始操作,并在完成后再次启用所有这些控件。
同意,这是更多的工作,但对用户来说看起来更好。

所以我认为使用asyncTask.Delay() 是更好的解决方案。

【讨论】:

    【解决方案2】:

    由于您处于应用程序的主线程中,因此当您处于睡眠部分时,屏幕不会发生任何更新(您已将整个程序置于睡眠状态) 要让更改出现,请执行 Application.DoEvents(); 在睡眠之前 - 这允许屏幕更新发生

    【讨论】:

    • 永远永远永远永远不要使用 Application.DoEvents() !!!!!!!!!这可能会导致事件顺序发生变化,从而给您带来更多麻烦。如果您需要执行 Application.DoEvents(),那么您的应用程序中存在根本性错误。
    • 请阅读thisthis
    • @GuidoG:虽然您不使用Application.DoEvents() 的警告是准确的,但我觉得讽刺的是,您随后会发布一个建议使用Control.Update() 的答案,这是一个糟糕的选择.如果您需要Update(),那么您的应用程序中存在根本性错误,就像需要DoEvents() 一样。
    • @PeterDuniho 这不是真的。尽管它们都对消息队列有影响,但 Control.Update() 没有像 DoEvents 那样的副作用。使用安全。我同意使用异步更好,但说它们同样糟糕实际上是错误的。
    • @GuidoG:你可以不同意所有你喜欢的。
    猜你喜欢
    • 2017-06-13
    • 1970-01-01
    • 2021-05-15
    • 1970-01-01
    • 2020-03-04
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多