Кстати, а где у тебя здесь инкремент curThreadCount ? :
private void btnStart_Click(object sender, EventArgs e)
{
foreach (int i in checkedIndices)
{
MyThreadClass clc = new MyThreadClass(paramString1,
new CallbackFunction(ThreadStart), //функция для обновления инфы формы при запуске потока
new CallbackFunction(ThreadDone)); //функция для обновления инфы формы при завершении работы потока (там мы удаляем поток из массива и уменьшаем число запущенных)
Thread t = new Thread(new ThreadStart(clc.CollectComputerLog));
t.IsBackground = true;
t.Start();
threads.Add(t);
while ((curThreadCount >= maxThreadCount) & (isRunning)) //проверка на достижение максимального количества запущенных потоков
UpdateTotalInfo();
if (!isRunning) //тот самый флажок
break;
}
В этом случае нужно также сделать lock:
lock (curThreadCount) curThreadCount++;
Иначе, в начале вся толпа стартовавших потоков захочет увеличить curThreadCount (с большой долей вероятности — одновременно), а в конце, когда ты всем потокам разошлёшь "аборты", они так же всей толпой страстно возжелают "опустить" твою curThreadCount на единичку, что приведёт к неправильному результату и к "висяку" программы на цикле. Поэтому, все данные, к которым возможен параллельный доступ из разных потоков должны закрываться или критическими секциями (lock) или взаимоисключающими блокировками (Mutex).