2015-10-20 1 views
3

Без цикла 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; 

     } 
    } 
} 
+1

Потому что вы не давая пользовательский интерфейс в любое время обновить, вместо того, чтобы использовать do..loop, использовать 'System.Windows .Forms.Timer' и запускайте его периодически. –

+1

Согласен. Нить будет навсегда занята «StartButton_Click_1», поэтому, даже если другое событие было запущено, а 'StopButton_Click' находится в очереди, он никогда не будет запущен, потому что другой метод никогда не заканчивается. Когда вы его исправили, подумайте о том, чтобы поле 'ContinuePing' было полем' volatile'. –

ответ

1

Try принуждать обновление метки после того, как вы изменили свой цвет:

GoogleStatusLabel.Refresh(); 
+0

Это было сделано. Это приводит меня к другой проблеме, я думаю, из-за таких потоков, как Pieter21. Но он работал на то, что я спросил. Благодаря! –

+0

Правильно - поскольку ваша петля только продолжается, у ui никогда не будет возможности обновиться. Если вы прослушиваете отдельный поток, вы не будете блокировать пользовательский интерфейс. –

0

Ваш процесс непрерывно работает в другом потоке, чем в потоке пользовательского интерфейса, который не получает время для обновления пользовательского интерфейса Предметы.

Использование Update/Обновить, чтобы заставить UI некоторое время обновления, или использовать сон, чтобы нить UI некоторое время

+0

Я не думаю, что это правда, нигде нигде не запускаются нити - все это происходит в 'button_click', запущенном из потока пользовательского интерфейса. Скорее всего, это тот случай, когда пользовательский интерфейс не обновляется, поскольку он постоянно работает и имеет нет времени для обновления. – Ric

+0

У меня есть обновленный цвет, однако я не могу взаимодействовать с пользовательским интерфейсом, потому что он застрял в постоянном цикле. Это еще одна проблема, над которой я сейчас работаю. –

+0

Извините, вы были правы, я был слишком занят тем, что произошло, когда у меня была аналогичная проблема. У кого нет;). По-прежнему остается вопрос о том, что у вас нет времени для обновления, но не для разных потоков. – Pieter21

1

Это, вероятно, потому, что петли работать достаточно быстро, и поэтому обновления не приемлемы.

Попробуйте добавить некоторый сон в петле, как

//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

+1

Спящий в потоке пользовательского интерфейса не позволяет обновлять пользовательский интерфейс, на самом деле вы можете получить «не отвечающий», если задержка достаточно длинная (5 секунд), и для нее не требуется ни одной задержки, цикл вызовет это. «BackgroundWorker» имеет проблемы с перекрестными потоками, о которых вам нужно знать. –

+1

Проблема заключается в том, что насос сообщений пользовательского интерфейса не работает, поэтому никаких фактических обновлений в пользовательском интерфейсе вообще нет. Сообщения, которые приведут к обновлению дисплея, ожидают завершения цикла, после чего последнее изменение будет отображаться после обработки сообщения. – Corey

0

Отметить обработчик Click() с async, а затем бросить свой цикл в await Task.Run() с анонимным делегатом. Обновление пользовательского интерфейса с помощью this.Invoke(), который я сделал ниже с вспомогательным методом:

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