Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
0 / 0 / 0
Регистрация: 05.10.2014
Сообщений: 67

ThreadPool - не все потоки учитываются при использовании в цикле

26.12.2015, 18:00. Показов 3665. Ответов 29

Студворк — интернет-сервис помощи студентам
При выполнении ThreadPool в цикле, после определённого количества циклов он зависает на строке 17(Monitor.Wait(workerLocker).
Точнее зависания как такового нет, он просто ждёт workerLocker, но не получает его. При этом runningWorkers = 1 (или2), где runningWorkers косвенно указывает на количество работающих потоков, которые должны бы были освободить workerLocker, но судя по всему они как то пропадают
Подскажите пожалуйста более надёжный способ выяснить, есть ли рабочие потоки в ThreadPool (и их количество), или, как решить вопрос с "пропадающими потоками" при использовании в цикле.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    class Program
    {
        static object workerLocker = new object();
        static int runningWorkers = 10;
        static int counter = 0;
 
        public static void Main()
        {
            for (int j = 0; j < 1000000; j++)
            {
                runningWorkers = 10;
                for (int i = 0; i < runningWorkers; i++)
                    ThreadPool.QueueUserWorkItem(Go, i);
 
                lock (workerLocker)
                  while (runningWorkers > 0)
                        Monitor.Wait(workerLocker);
            }
            Console.WriteLine("Готово! " + "Потоки выполнялись " + counter + " раз");
            Console.ReadLine();
        }
 
        public static void Go(object instance)
        {
            lock (workerLocker)
            {
                counter++;
                runningWorkers--;
                Monitor.Pulse(workerLocker);
            }
        }
    }
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
26.12.2015, 18:00
Ответы с готовыми решениями:

Как в ThreadPool проверить, что все потоки завершены
Как можно проверить, что все потоки завершили свою работу в ThreadPool, а после выполнить какое-нибудь действие?

Необходимо синхронизировать потоки (написать свой ThreadPool)
Надо написать свой ThreadPool. Идея начальная проста: есть очередь задач, которая подаётся на съедение потокам, всё инкапсулируется в...

Потоки, мультипоточность Task or Async/Await or ThreadPool?
Здравствуйте форумчане. Я очень нуждаюсь в вашей помощи. Я реализовываю парсер с одного довольно популярного сайта занятости и...

29
0 / 0 / 0
Регистрация: 05.10.2014
Сообщений: 67
30.12.2015, 12:40  [ТС]
Студворк — интернет-сервис помощи студентам
OwenGlendower, да, в чистом виде при малом объёме вычислений внутри потока CountdownEvent действительно быстрее. Но в случае если вычислений внутри потока много (как у меня) - то его влияние незначительно...
Но в любом случае он лучше того lock`a который я использовал.

Psilon, спасибо. Похоже, ваш код самый быстрый.
Но я не могу до конца разобраться с Partitioner.
В случае когда мой поток принимает 1 значение при использовании:
C#
1
2
3
4
Parallel.ForEach(source, elementХ =>
{
Console.WriteLine(elementХ);
});
всё просто - в elementХ я имею элемент своего массива.
А как в случае использования Partitioner получить элемент массива или хотя бы его индекс?
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
30.12.2015, 13:25
Лучший ответ Сообщение было отмечено Andreys5 как решение

Решение

Andreys5, ну в моем примере выше просто
C#
1
2
3
4
5
6
7
public static void Print(this double[] source, int startIndex, int endIndex)
{
   for(int i = startIndex; i < endIndex; i++)
   {
      Console.WriteLine(source[i]);      // че-то делаем с элементами массива
   }
}
То есть метод вызывается на некотором интервале индексов, а уж что с элементами массива делать - уже вы должны разбираться.

Добавлено через 5 минут
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
 
namespace ConsoleApplication29
{
    class Program
    {
        static void Main(string[] args)
        {
            var array = Enumerable.Range(1, 1024).ToArray();
            Print(array);
        }
 
        public static void Print<T>(T[] source)
        {
            Parallel.ForEach(Partitioner.Create(0, source.Length),
                             range =>
                             {
 
                                 Print(source, range.Item1, range.Item2);
                             });
        }
 
        private static void Print<T>(T[] source, int startIndex, int endIndex)
        {
            for (int i = startIndex; i < endIndex; i++)
            {
                Console.WriteLine(source[i]);      // че-то делаем с элементами массива
            }
        }
    }
}
0
30.12.2015, 15:27

Не по теме:

Цитата Сообщение от Psilon Посмотреть сообщение
object syncRoot = new object();
...
Цитата Сообщение от Psilon Посмотреть сообщение
lock (syncRoot)
Вот тут я не совсем понял. Зачем захватывать неиспользуемый объект? Я считал, что локом должен захватываться обрабатываемый ресурс, в данном случае result .

0
30.12.2015, 15:44

Не по теме:

Цитата Сообщение от aquaMakc Посмотреть сообщение
Я считал, что локом должен захватываться обрабатываемый ресурс, в данном случае result .
Неа, как раз не рекомендуется лочить объекты данных. По правильному - нужно лочить именно отдельно созданный объект. Более того, стандартные коллекции(List<>, Dictionary<> и т.д.) предоставляют уже готовый объект для этого. А интерфейс ICollection требует что бы вы создали такой объект.

Цитата Сообщение от aquaMakc Посмотреть сообщение
Зачем захватывать неиспользуемый объект?
Не важно используемый он или нет. Важно что его пытаются захватить несколько потоков и он выполняет роль семафора.

0
30.12.2015, 15:50

Не по теме:


Цитата Сообщение от Storm23 Посмотреть сообщение
стандартные коллекции(List<>, Dictionary<> и т.д.) предоставляют уже готовый объект для этого
т.е. код типа:
C#
1
2
3
4
5
6
7
8
9
List<TObject> ListName = new List <TObject>();
 
void ThreadWork()
{
    lock (ListName)
    {
       ...
    }
}
должен нормально лочить список для вызвавшего его протока?

0
30.12.2015, 16:30

Не по теме:

Цитата Сообщение от aquaMakc Посмотреть сообщение
должен нормально лочить список для вызвавшего его протока?
Нет. Здесь вы лочите как раз сам ListName. А по правильному нужно так:
C#
1
2
3
4
lock((list as ICollection).SyncRoot)
{
     ...
}

0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
30.12.2015, 16:40
Storm23, оффтопные посты не позволяют ставить "спасибо", так-то благодарю словами

Есть у меня определённая проблема с доступом к List из большого количества потоков. С SyncRoot стало лучше, но нет-нет, да наблюдаю
System.InvalidOperationException: Коллекция была изменена; невозможно выполнить операцию перечисления.
Но это тема отдельного топика.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
30.12.2015, 16:46
aquaMakc,
1) лочить нужно неиспользуемую переменную, как уже сказали выше
2) лично я избегаю lock-ов на публичные переменные, потому что вызывающий код уже мог сделать лок на Array.SyncRoot к примеру, и в таком случае я свалюсь в дедлок. Локальная переменная гарантирует то, что её лочить могу только я, и за счёт этого не будет блокировки потоков из-за кода типа
C#
1
2
3
4
5
lock (array.SyncRoot)
{
   var sum = array.Sum();
   Console.WriteLine(sum);
}
3
0 / 0 / 0
Регистрация: 05.10.2014
Сообщений: 67
30.12.2015, 17:56  [ТС]
Psilon, спасибо, всё работает.
Но после отработки цикла почти вся оперативная память остаётся забитой непонятно чем (массив для расчётов - пуст, результат - всего 1 значение).(такое ощущение что он хранит в памяти все отработанные потоки)
Не подскажите, как с этим бороться?
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
30.12.2015, 20:09
Andreys5, ну, тут обычно лучше запустить профилировщик и посмотреть, что память занимает. Так-то я сказать не могу Возможно память будет очищена по первому требованию системы (то есть объекты уже умерли, но их еще не собрал сборщик), а возможно где-то висячие ссылки остаются... Это уже нужно разбираться.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
30.12.2015, 20:09

Определение индекса массива в цикле при использовании указателей
Добрый день! Вопрос, в общем-то, ламерский, но что-то сам дотумкать не могу. Есть код, где заполняю одномерный массив элементами,...

Рандомные числа выдают один и тот же результат при их использовании в цикле
Всем доброго времени суток. У меня есть метод, в котором используются рандомные числа, чтобы взять из вектора имен - случайное имя и из...

При сортировке не учитываются отрицательные элементы
Доброго времени суток! При написании кода возникло 2 проблемы: 1) При сортировке не учитываются отрицательные элементы; ...

При компиляции не учитываются изменения, внесенные в проект
Скажите в чём может быть проблема,я запускаю отладку и почему-то вываливается смообщение ,которого уже нет в программе. Ошибок мне...

ссылки с rel=nofollow учитываются при подсчете тиц?
ссылки с rel=nofollow учитываются при подсчете тиц?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Новые блоги и статьи
Почему SEO не начинается с ключевых слов: что проверить до написания текстов
Neotwalker 01.08.2026
Когда владельцу сайта предлагают заняться SEO, первым шагом часто становится сбор запросов и написание текстов. Логика кажется понятной: 1. Находим ключевые слова. 2. Добавляем их на. . .
Знание — сила: Доктрина интенциональности знаний против массовых профанаций
Hrethgir 01.08.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11957&stc=1&d=1785567302 Знаменитый афоризм Фрэнсиса Бэкона «Знание — сила» (Scientia potentia est) в массовой культуре принято понимать. . .
SUNO Ai - Река Без Дна
zorxor 31.07.2026
Автор стихотворения - астрофизик Марина Катыс Ссылка на сгенерированную музыкальную композицию: https:/ / suno. com/ song/ 6f6e5464-b290-4650-be6c-44c85f8d8013 Я говорю, что Время- как вода течет. . .
Из невошедшего на форум (диалог с ИИ-гугла)
zorxor 29.07.2026
А вот, что интересно, сказал мне ИИ-гугла: Этот текст — эмоциональный пост пользователя под ником zorxor на интернет-форуме (вероятно, посвященном мистике, непознанному или альтернативной науке). . . .
Был праздник вчера, а я и не знал.
kumehtar 28.07.2026
27. 07. 2026г. Intel Core 2 Duo исполнилось 20 лет Салют, шампанское, овации! :drink:
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр. Дословно, отклонённая. . .
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru