При создании нового потока изменения в GUI не вносятся (C #) - PullRequest
2 голосов
/ 17 декабря 2011

С некоторой помощью мне удалось создать новый поток, хотя метод, по-видимому, выполняется, из-за условий метода появляется зеленый или красный свет, хотя при запуске метода (Check1..etc) без нового В потоке изменения отражаются в графическом интерфейсе (например, появляется красный / зеленый свет), но при создании нового потока и запуске метода изменения не отражаются в форме / графическом интерфейсе.

// Method / Action to start the checks         private void StartChecks_Click(object sender, EventArgs e)
        {

            Thread t = new Thread(
               o =>
               {
                   InitChecks();
               });
            t.Start();
        }

// Check1 public void Check1()
        {

            // lets grabs the info from the config!
            var lines = File.ReadAllLines("probe_settings.ini");
            var dictionary = lines.Zip(lines.Skip(1), (a, b) => new { Key = a, Value = b })
                                  .Where(l => l.Key.StartsWith("#"))
                                  .ToDictionary(l => l.Key, l => l.Value);

            // lets set the appropriate value for this check field
            label1.Text = dictionary["#CheckName1"];

            // lets define variables and convert the string in the dictionary to int for the sock.connection method!

            int portno1;
            int.TryParse(dictionary["#PortNo1"], out portno1);

            // Convert hostname to IP, performance issue when using an invalid port on a hostname using the TcpClient class! 
            IPAddress[] addresslist = Dns.GetHostAddresses(hostname2);

            foreach (IPAddress theaddress in addresslist)
            {
                // Attempt to create socket and connect to specified port on host
                TcpClient tcP = new System.Net.Sockets.TcpClient();
                try
                {
                    tcP.ReceiveTimeout = 1;
                    tcP.SendTimeout = 1;
                    tcP.Connect(theaddress, portno1);
                    displayGreen1();
                    tcP.Close();
                }
                catch
                {
                    displayRed1();
                }
            }

        }

// Change the lights when the condition is met

        public void displayGreen1()
        {
            pictureBox2.Visible = false;
            pictureBox1.Visible = true;
        }

        private void displayRed1()
        {
            pictureBox2.Visible = true;
            pictureBox1.Visible = false;
        }

Ответы [ 3 ]

3 голосов
/ 17 декабря 2011

Так устроен WinForms.Вы не можете вносить изменения из другого потока.Обычно решение заключается в использовании асинхронного делегата.

Прежде всего добавьте это объявление

 public delegate void MyDelegate1 ();

 public delegate void MyDelegate2 (); 

Затем, когда вы находитесь в другом потоке, вы должны сделать:

2 голосов
/ 17 декабря 2011

Это происходит потому, что элементы управления пользовательского интерфейса могут обновляться только из потока пользовательского интерфейса.Когда вы не создаете новый поток, код, который обновляет элементы управления, запускается в потоке пользовательского интерфейса, поэтому он работает так, как вы ожидаете.Когда вы делаете создаете новый поток, потому что этот поток не является потоком пользовательского интерфейса, код, который должен обновлять элементы управления, не может этого сделать.

Выможет гарантировать, что код, который обновляет элементы управления, выполняется в потоке пользовательского интерфейса, изменив вызовы методов на: -

this.BeginInvoke(new Action(() => displayRed1()));

и

this.BeginInvoke(new Action(() => displayGreen1()));

Между прочим (не связано с вашим текущимпроблема): -

Старайтесь избегать создания явного потока.Вместо этого используйте пул потоков для управления потоком за вас, например, ThreadPool.QueueUserWorkItem(x => InitChecks()).(Обратите внимание, что это все равно будет выполняться в потоке без пользовательского интерфейса, поэтому вам все равно нужно использовать BeginInvoke(), как описано выше.).Пул потоков лучше знает, когда создавать и выполнять поток, и его использование, в конечном счете, сделает ваш код более эффективным.

Старайтесь избегать перехвата всех типов исключений в ваших try{...}catch{...},Это говорит о том, что ваш код знает, что делать, если выброшено исключение любого типа .Вместо этого вылавливайте только те исключения, которые вы точно знаете, как обрабатывать,

, например,

try
{
    ...
}
catch(TcpException)
{
    ...
}
catch(AnotherKnownException)
{
    ...
}
...

Обратите внимание, что можно также иметь блок catch для all типы исключений, если вы перебрасываете исключение при выходе из блока,

например,

try
{
    ...
}
catch(KnownException)
{
    ...
}
catch(Exception)
{
    // perform some logging, rollback, etc.
    throw;
}
2 голосов
/ 17 декабря 2011

На вашем уровне навыков, было бы лучше:

  • используйте таймер в форме для проверки некоторой переменной состояния (скажем, bool _pb1Visible и bool _pb2Visible)
  • в обновлении таймера события в картинке
  • в потоке, обновите ТОЛЬКО переменные члена bool, упомянутые выше.

Это будет работать как шарм!

Простой пример:

В вашем Check1() методе вместо:

displayGreen1();

1021 * ставить *

_pb1Visible=true;
_pb1Visible=false;

и вместо

displayRed1();

1027 * ставить *

_pb1Visible=false;
_pb1Visible=true;

Поместите таймер в форму. В событии таймера выполните:

pictureBox2.Visible = _pb2Visible;
pictureBox1.Visible = _pb1Visible;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...