简体   繁体   English

“简单”C#时间线程似乎正在冻结

[英]“Simple” C# Time Thread Appears to be Freezing

I've been staring at this thread for some time and I believe my mind has shut down on it. 我已经盯着这个线程了一段时间,我相信我的思绪已经关闭了。 Thinking that the best thing to do, in order to update the time in a UI TextBox , would be to create what I thought would be a simple thread to get the time and post it back to the UI control. 认为最好的事情是,为了更新UI TextBox的时间,将创建我认为是一个简单的线程来获取时间并将其发布回UI控件。 After having fought with it for a while, I'm getting frustrated and thinking that I might just add the time in some other way. 在与它争吵了一段时间后,我感到沮丧并且认为我可能只是以其他方式增加时间。 In the intrepid spirit of the adventurer, I'm giving it another go. 在冒险家的强悍精神中,我再给它一次。

I've got a similar thread operating elsewhere in the app that takes a list and populates a DataGridView in a TabControl . 我在应用程序的其他地方运行了一个类似的线程,它接受一个列表并在TabControl填充DataGridView I'd have thought that the process would be roughly the same, but I'm missing a key part. 我原以为这个过程大致相同,但我错过了一个关键部分。 The entirety of the thread is below: 整个主题如下:

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;
    }

The above thread has been started in various places(in an attempt to debug), but is currently in the Form's Shown event handler. 上面的线程已在各个地方启动(试图调试),但目前在Form的Shown事件处理程序中。 The Form begins to appear, but then everything seems to hang. 表格开始出现,但一切似乎都挂了。 When I place a breakpoint in the thread, I can step ad infinitum , but the UI never seems to get control back. 当我在线程中放置断点时,我可以无限制地进行广告 ,但UI似乎永远无法控制回来。 What am I missing? 我错过了什么? I'll be happy to expand upon any neglected details. 我很乐意扩展任何被忽视的细节。

Edit: A clarification: This thread is being started in a function that is handling the Shown event. 编辑:澄清:此线程正在处理Shown事件的函数中启动。 The description of the Shown event is given as: Occurs whenever the Form is first shown. Shown事件的描述如下: 每当首次显示表单时发生。 I think that might eliminate the theory that the UI thread is Invoking too quickly. 我认为这可能会消除UI线程调用过快的理论。

The problem is that your while loop here is generating so many events that the event queue gets flooded: 问题是你的while循环产生了很多事件,事件队列被淹没了:

while (true)
{
    // ...
    updateClock(time, date);
}

Instead of doing this in a thread you can use a Timer to generate events at a regular interval and do one step of your method for each event. 您可以使用Timer定期生成事件,并为每个事件执行一个方法步骤,而不是在线程中执行此操作。 This will also mean that you don't have to use Invoke as the timer generates events on the main thread. 这也意味着您不必使用Invoke,因为计时器在主线程上生成事件。

There are also two other errors in your code: 您的代码中还有两个其他错误:

  • Occasionally TimeOfDay.ToString() could output a time that hits exactly at a second change, in which case the result of ToString() will not be "12:23:34.00000" but just "12:23:34" which will cause your method to throw an exception. 偶尔TimeOfDay.ToString()可以输出一个完全命中第二次更改的时间,在这种情况下,ToString()的结果不会是“12:23:34.00000”而只是“12:23:34”这将导致你的抛出异常的方法。
  • You are calling DateTime.Now twice, but the value could have changed in between the two calls. 您正在调用DateTime.Now两次,但两次调用之间的值可能已更改。 Normally this won't matter but as it passes midnight it could show '23:59:99.999' but the day shows as the next day. 通常这没关系,但是当它通过午夜时它可以显示'23:59:99.999',但是这一天显示为第二天。 It's probably not a significant error in this application but you ought to get into the habit of only calling DateTime.Now once when you want consistent values for the date and time. 这可能不是这个应用程序中的一个重大错误,但你应该养成只调用DateTime.Now的习惯,当你想要日期和时间的一致值时。

To fix these errors and to simplify your code: 要修复这些错误并简化代码:

  • Add a timer to your form. 在表单中添加计时器。
  • Set the timer's Enabled property to true in the designer. 在设计器中将计时器的Enabled属性设置为true
  • Add this event handler to the Tick event: 将此事件处理程序添加到Tick事件:

     private void timer_Tick(object sender, EventArgs e) { DateTime now = DateTime.Now; textBox1.Text = now.ToString("HH:mm:ss\\nyyyy-MM-dd"); } 

You may wish to adjust the format string depending on your needs. 您可能希望根据需要调整格式字符串

It doesn't surprise me that this isn't going well -- you're stuffing invokes in the UI thread message queue (with your BeginInvoke()) as fast as you can generate them. 这并不令我感到惊讶 - 这不是很好 - 你在UI线程消息队列(使用BeginInvoke())中填充调用的速度与生成它们的速度一样快。 You may want to put a break (ie with System.Threading.Thread.Sleep()) in your displayTime() thread to give the UI thread time to do some work. 您可能希望在displayTime()线程中放置一个中断(即使用System.Threading.Thread.Sleep()),以便为UI线程提供时间来完成某些工作。

How do you call displayTime ? 你怎么称呼displayTime

If your Form.Show() method is like this 如果您的Form.Show()方法是这样的

Show()
{
  displayTime();
}

Then as Mark answered you are blocking your main UI thread infinitely. 然后,当Mark回答你无限地阻止你的主UI线程。

I would start a new thread 我会开始一个新线程

Show()
{
   Action displayTimeAction = displayTime;

   displayTimeAction.BegingInvoke(null, null);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM