Ric*_*man 4 c# datetime multithreading
我已经盯着这个线程了一段时间,我相信我的思绪已经关闭了.认为最好的事情是,为了更新UI中的时间TextBox,将创建我认为是一个简单的线程来获取时间并将其发布回UI控件.在与它争吵了一段时间之后,我感到沮丧并且认为我可能只是以其他方式增加时间.在冒险家的强悍精神中,我再给它一次.
我有一个类似的线程在应用程序的其他地方运行,它接受一个列表并填充DataGridView一个TabControl.我原以为这个过程大致相同,但我错过了一个关键部分.整个主题如下:
private void displayTime()
{
while (true)
{
String time;
String date;
time = DateTime.Now.TimeOfDay.ToString();
int len = time.IndexOf('.');
time = time.Substring(0, len);
date = DateTime.Now.Date.ToString();
len = date.IndexOf(' ');
date = date.Substring(0, len);
updateClock(time, date);
}
}
private void updateClock(String time, String date)
{
if (InvokeRequired)
{
BeginInvoke(new timeDel(updateClock), new object[] {time, date});
return;
}
ctrlTimeTxt.Text = time + "\n" + date;
}
Run Code Online (Sandbox Code Playgroud)
上面的线程已经在各个地方启动(试图调试),但目前在Form的Shown事件处理程序中.表格开始出现,但一切似乎都挂了.当我在线程中放置断点时,我可以无限制地进行广告,但UI似乎永远无法控制回来.我错过了什么?我很乐意扩展任何被忽视的细节.
编辑: 澄清:此线程正在处理Shown事件的函数中启动.Shown事件的描述如下:每当首次显示表单时发生. 我认为这可能会消除UI线程调用过快的理论.
问题是你的while循环生成了很多事件,事件队列被淹没了:
while (true)
{
// ...
updateClock(time, date);
}
Run Code Online (Sandbox Code Playgroud)
您可以使用Timer定期生成事件,并为每个事件执行一个方法步骤,而不是在线程中执行此操作.这也意味着您不必使用Invoke,因为计时器在主线程上生成事件.
您的代码中还有两个其他错误:
TimeOfDay.ToString()会输出一个准确命中第二次更改的时间,在这种情况下,ToString()的结果将不是"12:23:34.00000"而只是"12:23:34"这将导致您的方法抛出异常.DateTime.Now两次,但两次调用之间的值可能已更改.通常这没关系,但是当它通过午夜时它可以显示'23:59:99.999',但是这一天显示为第二天.这可能不是这个应用程序中的一个重大错误,但你应该习惯只调用DateTime.Now一次你想要一致的日期和时间值.要修复这些错误并简化代码:
Enabled属性设置为true.将此事件处理程序添加到Tick事件:
private void timer_Tick(object sender, EventArgs e)
{
DateTime now = DateTime.Now;
textBox1.Text = now.ToString("HH:mm:ss\nyyyy-MM-dd");
}
Run Code Online (Sandbox Code Playgroud)您可能希望根据需要调整格式字符串.