c# - 使用已用秒表时间更新标签时遇到问题
问题描述
我想每隔一段时间更新一个标签,它需要一个方法来完成。我创建了一个秒表来获取经过的时间,并创建了一个 Windows 窗体计时器来通过 Tick 事件用经过的时间更新标签。我整理了我的问题的一个简短示例,请参见下文。
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
namespace SOWinFormsTest
{
public partial class Form1 : Form
{
private static Stopwatch watch = new Stopwatch();
private static System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
timer.Interval = 1000;
timer.Tick += timer_Tick;
timer.Start();
watch.Start();
SomeMethod();
watch.Stop();
}
private void timer_Tick(Object sender, EventArgs e)
{
label1.Text = GetTimeString(watch.Elapsed);
}
private string GetTimeString(TimeSpan elapsed)
{
string time = string.Empty;
time = string.Format("{0:00}:{1:00}:{2:00}.{3:000}",
elapsed.Hours,
elapsed.Minutes,
elapsed.Seconds,
elapsed.Milliseconds);
return time;
}
// Mimicking a method that takes 5 seconds to complete
// My actual code could take a lot longer
private void SomeMethod()
{
Thread.Sleep(5000);
}
}
}
当我运行此程序并单击我的按钮时,标签仅更新一次,即在 5 秒后SomeMethod()
完成。我希望标签随着经过的时间每秒更新一次。有谁知道为什么这不能按预期工作?这是多线程问题吗?我需要BackgroundWorker吗?还是我完全错过了一些东西?
解决方案
您正在主 GUI 线程SomeMethod
上执行您的。这将停止消息泵送。.NET WinForms 在隐藏 Windows 内部方面做得并不好,所以这成为一个问题。
简而言之,GUI 线程在“无限循环”中工作并处理来自 Windows 的消息,其中包括任何 GUI 更新消息、计时器消息、用户输入等(消息可能不仅来自 Windows,但这与这个问题无关)。
这里提到了这一点,假设您使用的是 .NET Framework 4.8: Timer class。
如果要测量方法的执行时间,则必须在单独的线程中运行它,以免阻塞 GUI 线程并获得更准确的结果(因为主线程上的 GUI 处理不会过多地影响执行时间)。
推荐阅读
- ios - 您可以让 Google OAuth 2.0 访问令牌持续更长时间吗?
- sql - 在 pgSQL 中结合 UPDATE 和 WINDOW
- haskell - 有没有一种方法可以多态地提升具有 monad 类型变量的类的实例,而不会重叠实例?
- java - JavaFX 中过滤后的 ObservableList 属性
- r - 带有权重和置信区间的发生率
- javascript - 使用 puppeteer 动态更改元素样式
- javascript - 如何将 NodeJS Web 服务器与 Electron 集成?
- java - 在 Sonarqube 插件中使用 Spring Boot 应用程序作为依赖项
- html - 当处于 :focus 状态时,输入类型“email”变为“text”
- javascript - 如何为 HTML 中的按钮启动脚本以更改字体大小?