Изменение GUI из другого потока

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by blackbox, 7 Jan 2016.

  1. blackbox

    blackbox Elder - Старейшина

    Joined:
    31 Dec 2011
    Messages:
    362
    Likes Received:
    62
    Reputations:
    11
    Я знаю, что тема заезженная, но почему-то у меня не работает код. Вот простой класс, который выполняет работу:

    Code:
    class test
        {
           
            public List<Thread> threads = new List<Thread>();
            public int nThreads = 0;
            public int maxThreads = 5;
            public ListBox Lb;
            public object obj = new object();
    
            public void DoWork(object data)
            {
              
                string mess = (string)data;
                //MessageBox.Show(mess);       
                Action action = () =>
                {
                    Lb.Items.Add(mess);
                };
    
                lock(obj)
                {
    
                    if (Lb.InvokeRequired)
                        this.Lb.Invoke(action);
                    else
                         action();               
    
                }     
                                 
                         
            }
    
            public void CreateThread(object data)
            {
                if (nThreads >= maxThreads)
                    return;
                Thread newThread = new Thread(DoWork);
                threads.Add(newThread);
                newThread.IsBackground = true;
                newThread.Start(data);
                nThreads++;
               
    
            }
    
            public void WindUpThreads()
            {
                //MessageBox.Show("count: " + nThreads.ToString());
                for(int i = 0; i < threads.Count; i++)
                {
                    if (threads[i].IsAlive == false)
                    {
                        threads[i].Abort();
                        threads.RemoveAt(i);
                       //MessageBox.Show("removing at " + i.ToString());
                    }
    
                }
    
                nThreads = threads.Count;
            }
           
        }

    А вот использование этого класса:

    Code:
    private void button1_Click(object sender, EventArgs e)
            {
                button1.Enabled = false;
                test thTest = new test();
                thTest.Lb = this.listBox1;
    
                string[] strings;
                try
                {
    
                    strings = File.ReadAllLines("C:\\users\\alex\\desktop\\test.txt");
                }
    
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return;
                }
                          
                bool flag = true;
                int counter = 0;
                int dataCount = strings.Length;
    
              
    
                while (flag == true)
                {
                    if (counter >= dataCount)
                    {
                        flag = false;
                    }
    
                    while (thTest.nThreads < thTest.maxThreads)
                    {
                        if (flag == false)
                            break;
                       
                        thTest.CreateThread(strings[counter]);
                       
                        counter++;
                    }
    
                    thTest.WindUpThreads();
    
                    if (flag == false)
                    {
                        do
                        {
                            thTest.WindUpThreads();
    
                        } while (thTest.nThreads != 0);
                    }
                   
    
    
                }
              
                listBox1.Items.Add("Done");
    
            }
    
    То есть я тупо передаю объект listBox1 в экземпляр рабочего класса. Но почему-то обновления не происходит, программа висит. Отладчик показывает что в месте где происходит Invoke вызывает исключение типа System.InvalidOperation. Почему так происходит, собственно?
     
  2. blackbox

    blackbox Elder - Старейшина

    Joined:
    31 Dec 2011
    Messages:
    362
    Likes Received:
    62
    Reputations:
    11
    В общем проблема была в том что цикл не давал форме обновлять интерфейс, поэтому его можно тоже в отдельном треде запустить.