@astrotrain

[C#] Как внести изменения в пользовательский интерфейс из другого потока другого класса?

У меня есть класс, который должен реализовать многопоточность (на примере все видно будет). Он совершает некие действия, и соответственно должен быть обновлен графический интерфейс. Я знаю что это дурная практика, связывать гуи и логику (для этого вроде как события нужно использовать), но в данный момент мне нужно разобраться именно с таким подходом. Вот код класса

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Windows.Forms;
using System.Collections;
using System.Threading;

namespace WindowsFormsApplication2
{
   
    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)
                    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;
        }
        
    }

      

}


То есть, я передаю в него объект listbox и в определенное время вызываю invoke. Вот как класс вызывается с формы:

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.Threading;
using System.IO;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        public object obj = new object();
        public Form1()
        {
            InitializeComponent();

           //MessageBox.Show("Done");
           //thTest.WindUpThreads();
           //MessageBox.Show(thTest.nThreads.ToString());
           
            
        }

        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            test thTest = new test();
            thTest.Lb = 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");

        }

             

    }
}


Но программа виснет, а в отладчике на месте invoke показано исключение(которое почему-то не выбрасывается):

+		Lb	{SelectedItem = "((System.Windows.Forms.Control)(Lb)).Text" запустило исключение типа "System.InvalidOperationException"}	System.Windows.Forms.ListBox


В чем может быть вообще проблема? Что я пропустил? Ведь это простой пример, он должен работать.
  • Вопрос задан
  • 584 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы