【问题标题】:Why does my loop not allow my labels color to change?为什么我的循环不允许我的标签颜色改变?
【发布时间】:2015-10-20 12:59:26
【问题描述】:

没有 do 循环,我的代码运行良好。一旦我将它放在 do 或 while 循环中,代码就无法更新颜色状态。任何的想法?根据我从互联网上收集的信息,我的循环编写正确。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.NetworkInformation;
using System.Threading;



namespace SystemsUpDown
{
    public partial class MainForm : Form
    {

        public MainForm()
        {
            InitializeComponent();
        }

        bool ContinuePing = false;


        private void QuitButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void StartButton_Click_1(object sender, EventArgs e)
        {
            Ping ping = new Ping();
            ContinuePing = true;
            do
            {
                try ///ping google
                {
                    PingReply reply = ping.Send("8.8.8.8");

                    if (reply.Status == IPStatus.Success)
                    {
                        GoogleStatusLabel.BackColor = Color.Green;
                    }

                }
                catch
                {
                    GoogleStatusLabel.BackColor = Color.Red;
                }

                try ///ping Yahoo!
                {
                    PingReply reply = ping.Send("www.yahoo.com");

                    if (reply.Status == IPStatus.Success)
                    {
                        YahooStatusLabel.BackColor = Color.Green;
                    }

                }
                catch
                {
                    YahooStatusLabel.BackColor = Color.Red;
                }

                try ///ping Reddit.com
                {
                    PingReply reply = ping.Send("www.reddit.com");

                    if (reply.Status == IPStatus.Success)
                    {
                        RedditStatusLabel.BackColor = Color.Green;
                    }

                }
                catch
                {
                    RedditStatusLabel.BackColor = Color.Red;
                }

                try ///ping Chive
                {
                    PingReply reply = ping.Send("www.chive.com");

                    if (reply.Status == IPStatus.Success)
                    {
                        ChiveStatusLabel.BackColor = Color.Green;
                    }

                }
                catch
                {
                    ChiveStatusLabel.BackColor = Color.Red;
                }

                try ///ping CNN
                {
                    PingReply reply = ping.Send("www.cnn.com");

                    if (reply.Status == IPStatus.Success)
                    {
                        CNNStatusLabel.BackColor = Color.Green;
                    }

                }
                catch
                {
                    CNNStatusLabel.BackColor = Color.Red;
                }

            } while (ContinuePing);

        }

        private void StopButton_Click(object sender, EventArgs e)
        {
            GoogleStatusLabel.BackColor = Color.Yellow;
            ChiveStatusLabel.BackColor = Color.Yellow;
            CNNStatusLabel.BackColor = Color.Yellow;
            RedditStatusLabel.BackColor = Color.Yellow;
            YahooStatusLabel.BackColor = Color.Yellow;
            ContinuePing = false;

        }
    }
}

【问题讨论】:

  • 因为你没有给 UI 任何时间来更新,而不是使用 do..loop,使用 System.Windows.Forms.Timer 并定期运行它。
  • 同意。线程将永远忙于StartButton_Click_1,因此即使另一个事件已触发并且StopButton_Click 处于“队列中”,它也永远不会运行,因为另一个方法永远不会完成。修复后,请考虑将字段 ContinuePing 设置为 volatile 字段。

标签: c# do-loops


【解决方案1】:

尝试在更改颜色后强制刷新标签:

GoogleStatusLabel.Refresh();

【讨论】:

  • 做到了。由于提到了像 Pieter21 这样的线程,这导致了我认为的另一个问题。但它适用于我的要求。谢谢!
  • 正确 - 因为你的循环只是继续,用户界面永远没有机会刷新。如果您在单独的线程上执行 ping 操作,则不会锁定 UI。
【解决方案2】:

这可能是因为循环运行得足够快,因此更新无法理解。

尝试在循环中添加一些睡眠

//Sleep for two seconds. You can add this at end of loop.
//Or, sleep for 2 secs after pinging one site. 
// 2000 miliseconds = 2 seconds.
System.Threading.Thread.Sleep(2000);

然后检查。

我建议您为此使用 BackgroundWorker。因为主线程中的这个while循环会挂起主窗体。

BackgroundWorker 适合这样定期更新窗体控件,使主窗口不会挂起。 请参考以下链接—— https://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

【讨论】:

  • 在 UI 线程中休眠不会让 UI 更新,实际上如果延迟足够长(5 秒),您可能会得到“无响应”,并且不需要是一个单一的延迟,循环会导致它。 BackgroundWorker 有你需要注意的跨线程问题。
  • 问题在于 UI 消息泵没有运行,因此根本没有在 UI 上进行实际更新。会导致显示更新的消息正在排队等待循环退出,此时,一旦消息得到处理,将显示最后的更改。
【解决方案3】:

您的进程一直在与 UI 线程不同的线程上运行,因此没有时间更新 UI 项。

使用 Update/Refresh 强制 UI 一些更新时间,或者使用 sleep 让 UI 线程有一些时间

【讨论】:

  • 我不认为这是真的,任何地方都没有启动线程 - 这一切都发生在从 UI 线程启动的 button_click 内 - 很可能只是 UI 没有更新的情况因为它一直在运行,没有时间更新。
  • 我拥有的是更新后的颜色,但是我无法与 UI 交互,因为它现在卡在一个恒定的循环中。这是我现在正在解决的另一个问题。
  • 对不起,你是对的,当我遇到类似问题时,我太专注于发生的事情。谁没有;)。还是没来得及更新的问题,但不是在不同的线程上
  • 要与 UI 交互,请使用来自不同答案的 BackgroundWorker。
  • @MichaelFhqwhgads - 当然,也许可以查看 BackGroundWorker 之类的内容,建议执行更新并考虑不要经常 ping 同一个地址!
【解决方案4】:

使用async 标记Click() 处理程序,然后将您的循环放入带有匿名委托的await Task.Run()。使用 this.Invoke() 更新 UI,我在下面使用辅助方法完成了这项工作:

    private async void StartButton_Click_1(object sender, EventArgs e)
    {
        await Task.Run(() =>
        {
            Ping ping = new Ping();
            ContinuePing = true;
            do
            {
                try ///ping google
                {
                    PingReply reply = ping.Send("8.8.8.8");

                    if (reply.Status == IPStatus.Success)
                    {
                        SetLabelColor(GoogleStatusLabel.BackColor, Color.Green);
                    }

                }
                catch
                {
                    SetLabelColor(GoogleStatusLabel.BackColor, Color.Red);
                }

                try ///ping Yahoo!
                {
                    PingReply reply = ping.Send("www.yahoo.com");

                    if (reply.Status == IPStatus.Success)
                    {
                        SetLabelColor(YahooStatusLabel.BackColor, Color.Green);
                    }

                }
                catch
                {
                    SetLabelColor(YahooStatusLabel.BackColor, Color.Red);
                }

                try ///ping Reddit.com
                {
                    PingReply reply = ping.Send("www.reddit.com");

                    if (reply.Status == IPStatus.Success)
                    {
                        SetLabelColor(RedditStatusLabel.BackColor, Color.Green);
                    }

                }
                catch
                {
                    SetLabelColor(RedditStatusLabel.BackColor, Color.Red);
                }

                try ///ping Chive
                {
                    PingReply reply = ping.Send("www.chive.com");

                    if (reply.Status == IPStatus.Success)
                    {
                        SetLabelColor(ChiveStatusLabel.BackColor, Color.Green);
                    }

                }
                catch
                {
                    SetLabelColor(ChiveStatusLabel, Color.Red);
                }

                try ///ping CNN
                {
                    PingReply reply = ping.Send("www.cnn.com");

                    if (reply.Status == IPStatus.Success)
                    {
                        SetLabelColor(CNNStatusLabel, Color.Green);
                    }

                }
                catch
                {
                    SetLabelColor(CNNStatusLabel, Color.Red);
                }

            } while (ContinuePing);
        });
    }

    private void SetLabelColor(Label lbl, Color clr)
    {
        this.Invoke((MethodInvoker)delegate {
            lbl.BackColor = clr;
        });
    }

【讨论】:

    猜你喜欢
    • 2015-10-27
    • 2020-10-13
    • 1970-01-01
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    • 2010-10-15
    • 1970-01-01
    相关资源
    最近更新 更多