Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как оповестить о конче работы потоков, Очень много потоков надо синхронизироват 
:(
    Опции темы
RYB
  Дата 12.8.2008, 21:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 17.1.2007

Репутация: нет
Всего: нет



Здравствуйте.
Такая вот задачка: есть много потоков (1-3000 а может даже и больше из плодится). Каждый делает свою работу - обрабатывание около 100 мегабайт страниц html и запись данных в mysql.

Создаю я их через делегаты и соответственно вызываю методом BeginInvoke()  (пишу на C# .net 3.5)

Ну вот наплодил я 3000 потоков, главная программа всю свою задачу выполнила и хочет закрываться.
От того чтоб закрыться прежде времени ее отделяет только Console.ReadLine(). 

Хоть это и самое ресурсощадящее решение, оно не самое удобное так как понять что все 3000 потоков закрылись тяжело.

пробовал сохранять от каждого BeginInvoke() экземпляры класса IAsyncResult, а потом после вызова всех детищь, их в цикле остонавливать через EndInvoke() - но тогда весь процес дико тормозит (не машина тормозит, а процес замедляется и программа работает буд-то в однопоточном режиме)

Кто какие способы использовал и может поделится опытом?
PM MAIL WWW   Вверх
Partizan
Дата 12.8.2008, 22:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 18
Всего: 67



RYB, при окончании работы потока должно происходить соответствующее событие, на которое вызывающий должен подписаться...


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
RYB
Дата 12.8.2008, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 17.1.2007

Репутация: нет
Всего: нет



Partizan, Спасибо за ответ.
А можно поподробнее: какое именно событие и как подписаться на его поимку?

Добавлено через 7 минут и 45 секунд
Я кажется понял о чем ты говориш: при вызове BeginInvoke() я указываю CallBack метод, котрый будет вызван по завершению работы потока. Проблема в том что тогда прийдется в так-сказать main() писать бесконечный цикл для проверки условия совпадения числа потоков запущеных и отработавших.
Но это будет хавать цп.

А есть ли способ завершить главный поток вторичным?
PM MAIL WWW   Вверх
Partizan
Дата 12.8.2008, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 18
Всего: 67



пускай по таймеру проверяется число запущенных и остановленных и всё...и цп не будет загружен выполнением бесконечного цикла...


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
RYB
Дата 12.8.2008, 22:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 17.1.2007

Репутация: нет
Всего: нет



Как вариант использовать можно. Даже и без таймера
Код

while (true)
            {
                Thread.Sleep(1000);
            }


Спасибо за идею, Partizan.

Но всетаки интересно: если еще решение поэлегантнее?

PM MAIL WWW   Вверх
Akina
Дата 12.8.2008, 23:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: нет
Всего: 454



Не понимаю... почему нельзя формирование сигнала на завершение работы приложения возложить именно на CallBack-функцию?

В самом начале работы заводим счетчик int counter, запихиваем туда единичку. Инкрементируем, запуская очередной поток. Callback, кроме всего прочего, декрементирует счетчик. Когда все функции основной программы выполнены, вызываем сами эту callback, после чего запускаем просто цикл валяния дурака ( while (counter>0) {Thread.Sleep(1000);} подойдет).
Если на момент ручного запуска callback потоков больше нет, счетчик обнулится. Если есть - он обнулится при завершении последнего потока. Вот по этому нулю цикл сдвинется и работа приложения завершится.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Felan
Дата 13.8.2008, 07:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 2.8.2007
Где: Самара

Репутация: нет
Всего: 7



Я извиняюсь, если что... в .Net не сильно пока еще разбираюсь, но вроде как для таких целей можно использовать спец. объекты синхронизации - семафоры.
Не знаю, можно их использовать под .Net...

ЗЫЖ В Делфи точно можно smile Вот статья, хотя она и про делфи, но вроде это все WinAPI... так что наверно без разницы.

Это сообщение отредактировал(а) Felan - 13.8.2008, 07:33


--------------------
// Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного.
PM MAIL WWW ICQ   Вверх
Partizan
Дата 13.8.2008, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 18
Всего: 67



Felan, в данном случае не подходит....


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
RYB
Дата 13.8.2008, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 17.1.2007

Репутация: нет
Всего: нет



Цитата(Akina @  12.8.2008,  23:15 Найти цитируемый пост)
Не понимаю... почему нельзя формирование сигнала на завершение работы приложения возложить именно на CallBack-функцию?

В самом начале работы заводим счетчик int counter, запихиваем туда единичку. Инкрементируем, запуская очередной поток. Callback, кроме всего прочего, декрементирует счетчик. Когда все функции основной программы выполнены, вызываем сами эту callback, после чего запускаем просто цикл валяния дурака ( while (counter>0) {Thread.Sleep(1000);} подойдет).
Если на момент ручного запуска callback потоков больше нет, счетчик обнулится. Если есть - он обнулится при завершении последнего потока. Вот по этому нулю цикл сдвинется и работа приложения завершится.


Почему нельзя, можно и нужно - это я и отметил как решение.
Но из опыта: на одну задачю есть масса решений. Поэтому для того чтобы прога работала оптимально и для саморазвития мне интересно какие есть еще варианты.

Но видать проще решине врятли найдется.

Идея с симофорами (если я ее правильно понял) в данной ситуации не подходит, так как для каждого потока (а их тут куча) необходимо вызвать метод EndInvoke()  - Аналог WaitForSingleObject() что и было описано выше.
PM MAIL WWW   Вверх
Akina
Дата 13.8.2008, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: нет
Всего: 454



То, что семафоры (а равно и мутексы) не подходят - это очевидно. Их надо опрашивать, а поллинг никогда не относился к красивым решениям, если есть альтернатива.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Felan
Дата 13.8.2008, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 2.8.2007
Где: Самара

Репутация: нет
Всего: 7



Цитата(RYB @  13.8.2008,  13:01 Найти цитируемый пост)
Идея с симофорами (если я ее правильно понял) в данной ситуации не подходит, так как для каждого потока (а их тут куча) необходимо вызвать метод EndInvoke()  - Аналог WaitForSingleObject() что и было описано выше. 

Возможно я не так понял твой первый пост... Если тебе надо самому завершить все потоки, когда твой основной поток отработал, то да... А если тебе надо дождаться когда они все отработают сами, то нет.

Во втором случае логика такая:

Ты создаешь семафор. Каждый дополнительный поток при старте его захватывает - у него увеличивается счетчик, а при завершении освобождает - счетчик уменьшается (такова суть семафора). В основном потоке ты просто ждешь пока семафор освободится полностью - его счетчик станет равным 0 (все захватившие его потоки завершились).
Функция ожидания не будет кушать такты процессора.

Смею утверждать, что семафоры именно для ожидания завершения многих потоков и предназначены...




--------------------
// Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного.
PM MAIL WWW ICQ   Вверх
Partizan
Дата 13.8.2008, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 18
Всего: 67



Felan, семафоры предназначены для управления доступом к общим ресурсам. Если надо будет отслеживать завершение каждого отдельного потока, идея с семафорами сразу отпадает.


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
RYB
Дата 13.8.2008, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 17.1.2007

Репутация: нет
Всего: нет



Цитата(Felan @  13.8.2008,  12:00 Найти цитируемый пост)
Ты создаешь семафор. Каждый дополнительный поток при старте его захватывает - у него увеличивается счетчик, а при завершении освобождает - счетчик уменьшается (такова суть семафора). В основном потоке ты просто ждешь пока семафор освободится полностью - его счетчик станет равным 0 (все захватившие его потоки завершились).


Тогда я не видел нечего похожего в .net.
Есть только другие варианты реализации которые несут похожую функциональность:
снова тотже CallBack
PM MAIL WWW   Вверх
Felan
Дата 13.8.2008, 12:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 2.8.2007
Где: Самара

Репутация: нет
Всего: 7



Цитата(Partizan @  13.8.2008,  14:10 Найти цитируемый пост)
Felan, семафоры предназначены для управления доступом к общим ресурсам. Если надо будет отслеживать завершение каждого отдельного потока, идея с семафорами сразу отпадает.


Блин. Точно... они же не в ту сторону считают :(


Это сообщение отредактировал(а) Felan - 13.8.2008, 13:26


--------------------
// Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного.
PM MAIL WWW ICQ   Вверх
Felan
Дата 13.8.2008, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 284
Регистрация: 2.8.2007
Где: Самара

Репутация: нет
Всего: 7



А если что-нибудь подобное сделать? Вроде не должно тормозить... Понимаю, что сделано не совсем так, как изначально делал автор, но просто для иллюстрации идеи может сойдет? smile

Код

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

namespace ConsoleApplication1
{
    public class Program
    {   
        private static readonly ManualResetEvent  ev = new ManualResetEvent(false);
        private static readonly Object lockObj = new Object();
        private static int threadCount = 0;

        public static void changeThreadCount(int value)
        {
            lock(lockObj)
            {
                threadCount += value;

                if (threadCount != 0 )
                {
                    ev.Reset();
                }
                else
                {
                    ev.Set();
                }
            }
        }
        public static int getThreadCount()
        {
            lock(lockObj)
            {
                return threadCount;
            }
        }

        public static void Main()
        {
            Console.WriteLine("Start threads creation");
            for( int i = 0; i < 5; i++)
            {
                Thread thread = new Thread(threadMethod);
                thread.Name = "Thread " + i;
                thread.Start();

                Thread.Sleep(100);
            }
            Console.WriteLine("End threads creation");

//            ev.WaitOne(); // Эта строка как раз ждет завершения всех потоков.

            Console.WriteLine("End program");
            Console.ReadKey(); //Это просто для того, что бы видеть результат теста :)
        }

        private static void threadMethod()
        {
            changeThreadCount(1);
            try
            {
                int i = 0;
                Random rnd = new Random(100);
                while (i < 7)
                {
                    i++;
                    Console.WriteLine("Thread {0}", Thread.CurrentThread.Name);
                    Thread.Sleep( rnd.Next(100, 200));
                }
            }
            finally
            {
                changeThreadCount(-1);
            }
        }
    }       
}




--------------------
// Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного.
PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0930 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.