У меня есть класс, который должен реализовать многопоточность (на примере все видно будет). Он совершает некие действия, и соответственно должен быть обновлен графический интерфейс. Я знаю что это дурная практика, связывать гуи и логику (для этого вроде как события нужно использовать), но в данный момент мне нужно разобраться именно с таким подходом. Вот код класса
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
В чем может быть вообще проблема? Что я пропустил? Ведь это простой пример, он должен работать.