Помощь Регистрация
Страница 1 из 2 12 ПоследняяПоследняя
Показано с 1 по 25 из 28
  1. #1
    Аватар для Stas_K
    Регистрация
    24.01.2006
    Пол
    Пол: Мужской
    Авто
    Chevrolet Cruze
    Возраст
    41
    Сообщений
    934
    Благодарности

    Пишу многозадачную прогу. Нужна помощь!

    Вопрос к программерам.

    Нужно написать парсер интернет-страниц в несколько потоков.
    Пишу на Delphi.
    Поскольку с многозадачностью сталкиваюсь впервые, есть несколько вопросов.

    С закачкой страницы в отдельном потоке я с горем пополам разобрался (TThread для организации потока и TIdHttp для запроса страницы).

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

  2. #2
    Stealth™
    Guest
    Вот тут почитай.

    http://relib.com/Forums/Forum8-1.aspx

    Удачи тебе с потоками

  3. #3
    Аватар для Nusferatus
    Регистрация
    01.12.2006
    Пол
    Пол: Мужской
    Авто
    BMW m3
    Сообщений
    39 637
    Благодарности
    Цитата Сообщение от Stas_K Посмотреть сообщение
    Вопрос к программерам.

    Нужно написать парсер интернет-страниц в несколько потоков.
    Пишу на Delphi.
    Поскольку с многозадачностью сталкиваюсь впервые, есть несколько вопросов.

    С закачкой страницы в отдельном потоке я с горем пополам разобрался (TThread для организации потока и TIdHttp для запроса страницы).

    Проблема в следующем:
    После того, как поток получил ответ на запрос, он должен как-то передать в головной процесс информацию об этом. Как это сделать?
    Можно ли в головном процессе обрабатывать какое-нибудь виндовое событие, которое происходит при завершении работы потока?
    Или тупо гонять цикл и опрашивать созданные потоки?
    Через очередь сообщений приложения попробуй.
    Я в дэльфи мало чего понимаю - помню смутно лишь по школе, но на си там проще простого..

  4. #4
    Аватар для Nusferatus
    Регистрация
    01.12.2006
    Пол
    Пол: Мужской
    Авто
    BMW m3
    Сообщений
    39 637
    Благодарности
    Вот как-то так ты его инициализируешь:
    HANDLE CreateThread(
    LPSECURITY_ATTRIBUTES lpThreadAttributes, // указатель на атрибуты
    DWORD dwStackSize, // размер стека потока в байтах
    LPTHREAD_START_ROUTINE lpStartAddress, // указатель на функцию потока
    LPVOID lpParameter, // аргумент для нового потока
    DWORD dwCreationFlags, // флаг создания
    LPDWORD lpThreadId // указатель на возвращаемый номер потока
    );

    Далее, твой поток выполняется, пока не произошло одно из следующих событий:
    1. Поток вызвал одну из функций: ExitThread, ExitProcess, TerminateThread или TerminateProcess
    2. Завершился цикл и произошел выход из функции (return).

    Функция GetExitCodeThread возвращает статус завершения потока. Пока поток выполняется, он имеет статус завершения STILL_ACTIVE, при завершении он меняется на код выхода из потока.

    Собсно по ней ты и можешь в основном процессе выяснить чем закончилась байда с твоим потоком.
    Либо анализируй в цикле где-нить значение хэндла твоего потока. Если не NULL, значь всё ещё вертится.
    Так же никто ен отменял общение между потоками и головным процессом при помощи глобальных переменных.
    Ну и как я сказал - при помощи очереди сообщений приложения.
    Посылать их можно функцией Win32 API SendMessage(...), при этом естессно использовать не забронированные системой идентификаторы, а WM_USER + index. Далее любую инфу ты можешь передавать через lParam. В общем масса вариантов.

  5. #5
    Аватар для Nusferatus
    Регистрация
    01.12.2006
    Пол
    Пол: Мужской
    Авто
    BMW m3
    Сообщений
    39 637
    Благодарности
    ЗЫ. Кстати в winapi есть ещё такая прикольная функция GetThreadTimes, которая возвращает время, затраченное процессором на обработку указанного потока))

  6. #6
    Аватар для Nusferatus
    Регистрация
    01.12.2006
    Пол
    Пол: Мужской
    Авто
    BMW m3
    Сообщений
    39 637
    Благодарности
    Ещё вспомнил.. При помощи WaitForSingleObject можно подождать завершения потока в основном цикле обработки сообщений процесса.

  7. #7
    Аватар для Stas_K
    Регистрация
    24.01.2006
    Пол
    Пол: Мужской
    Авто
    Chevrolet Cruze
    Возраст
    41
    Сообщений
    934
    Благодарности
    Цитата Сообщение от Nusferatus Посмотреть сообщение
    Ещё вспомнил.. При помощи WaitForSingleObject можно подождать завершения потока в основном цикле обработки сообщений процесса.
    Вот ждать-то как раз не надо.
    Нужно, чтобы в момент завершения работы потока (то есть, когда получена запрашиваемая интернет-страница) головной процесс сразу же полученную страницу обработал и запустил запрос следующей страницы.

  8. #8
    Аватар для Nusferatus
    Регистрация
    01.12.2006
    Пол
    Пол: Мужской
    Авто
    BMW m3
    Сообщений
    39 637
    Благодарности
    Цитата Сообщение от Stas_K Посмотреть сообщение
    Вот ждать-то как раз не надо.
    Нужно, чтобы в момент завершения работы потока (то есть, когда получена запрашиваемая интернет-страница) головной процесс сразу же полученную страницу обработал и запустил запрос следующей страницы.
    См. выше. 3 способа передачи данных между потоками.
    Я использую всегда глобальные переменные в таком случае ибо это удобнее.
    Их можно использовать даже при вызове хука из длл, хотя в таком случае гораздо сподручнее передавать любую структуру через Lparam.

    Матчасть по данной теме можно покурить на rzdn.ru. Там и форумы есть.
    ЗЫ. Дельфа дельфой, но win32 api никто не отменял
    Последний раз редактировалось support; 13.03.2008 в 09:14.

  9. #9
    Аватар для Stas_K
    Регистрация
    24.01.2006
    Пол
    Пол: Мужской
    Авто
    Chevrolet Cruze
    Возраст
    41
    Сообщений
    934
    Благодарности
    Нашел более цивилизованный метод!
    В потоке создал событие OnComplete, которое в головной программе привязал к процедуре. Работает!
    SendMessage - тоже вариант, но не хочется заморачиваться...

  10. #10
    Stealth™
    Guest
    Цитата Сообщение от Stas_K Посмотреть сообщение
    В потоке создал событие OnComplete.
    Малацца!

  11. #11
    Аватар для Nusferatus
    Регистрация
    01.12.2006
    Пол
    Пол: Мужской
    Авто
    BMW m3
    Сообщений
    39 637
    Благодарности
    Цитата Сообщение от Stas_K Посмотреть сообщение
    Нашел более цивилизованный метод!
    В потоке создал событие OnComplete, которое в головной программе привязал к процедуре. Работает!
    SendMessage - тоже вариант, но не хочется заморачиваться...
    Ыыы))) Вапщето теже яйца, вид сбоку)))

  12. #12

    Регистрация
    11.02.2005
    Авто
    2114
    Сообщений
    1 209
    Благодарности
    рискну предположить, что твой OnComplete, в лучшем случае, свойство типа TNotifyEvent. или просто член класса. при завершении, поток вызывает этот делегат(сори за плюсовую терминологию), который, к примеру, добавляет в како-нить контейнер полученные данные. успешность этой операции сильно зависит от начального дезайна этой архитектуры. чтобы все работало без объектов синхронизации, можно было бы сделать примерно так(я почти не думал над этим, задача слишком обстрактная): какой-нить главный поток создает массив указателей на данные, к примеру с N ячейками. создает N потоков, указывая им, какие сайты они должны скачать, и в какие ячейки положить указатели на полученные данные. каждый рабочий поток, когда скачает, разместит в памяти, и сделает всю работу, записывает указатель в массив. главный поток спит (Sleep())циклически проверяя, что все ячейки массива перестали быть nil. когда они перестали, он обрабатывает эти данные, и потом освобождает память.
    недостатки этого подхода:
    1 - главный. можно гарантировать, что без синхронизации разложение (corruption) данных не произойдет, на 32-битной платформе Intel, где массив указателей выровнен на 4-байта. операция записи такого указателя будет атомарной.
    достоинства:
    1 - сомнительное. не использованы объекты синхронизации.

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

  13. #13
    Аватар для Nusferatus
    Регистрация
    01.12.2006
    Пол
    Пол: Мужской
    Авто
    BMW m3
    Сообщений
    39 637
    Благодарности
    Цитата Сообщение от Модуль Оверлеев Посмотреть сообщение
    рискну предположить, что твой OnComplete, в лучшем случае, свойство типа TNotifyEvent. или просто член класса. при завершении, поток вызывает этот делегат(сори за плюсовую терминологию), который, к примеру, добавляет в како-нить контейнер полученные данные. успешность этой операции сильно зависит от начального дезайна этой архитектуры. чтобы все работало без объектов синхронизации, можно было бы сделать примерно так(я почти не думал над этим, задача слишком обстрактная): какой-нить главный поток создает массив указателей на данные, к примеру с N ячейками. создает N потоков, указывая им, какие сайты они должны скачать, и в какие ячейки положить указатели на полученные данные. каждый рабочий поток, когда скачает, разместит в памяти, и сделает всю работу, записывает указатель в массив. главный поток спит (Sleep())циклически проверяя, что все ячейки массива перестали быть nil. когда они перестали, он обрабатывает эти данные, и потом освобождает память.
    недостатки этого подхода:
    1 - главный. можно гарантировать, что без синхронизации разложение (corruption) данных не произойдет, на 32-битной платформе Intel, где массив указателей выровнен на 4-байта. операция записи такого указателя будет атомарной.
    достоинства:
    1 - сомнительное. не использованы объекты синхронизации.

    короче, я бы так делать не стал. для винды существует очень быстрая и легковесная критическая секция, которая прекрасно синхрит потоки в одном процессе.
    +1
    Всё верно.
    Щас интереса ради залез в азбуку дельфей, поглазеть как там что реализовано с потоками)) Одно скажу ребята: C++ рулид!)))

  14. #14
    Аватар для Stas_K
    Регистрация
    24.01.2006
    Пол
    Пол: Мужской
    Авто
    Chevrolet Cruze
    Возраст
    41
    Сообщений
    934
    Благодарности
    Цитата Сообщение от Nusferatus Посмотреть сообщение
    Одно скажу ребята: C++ рулид!)))
    Нет времени с C++ разбираться. Да и на Delphi насобачился уже.

    Цитата Сообщение от Модуль Оверлеев Посмотреть сообщение
    не использованы объекты синхронизации.
    Я не совсем разобрался в потоках, но синхронизация есть. Собственно, результате синхронизации событие и происходит (если не ошибаюсь).
    Вот так в модуле потока все выглядит:

    procedure TDownloadThread.Execute;
    begin
    try
    IdHttp:=TIdHttp.Create(nil);
    IdHttp.AllowCookies:=True;
    IdHttp.AuthRetries:=5;
    IdHttp.HandleRedirects:=False;
    IdHttp.Port:=80;
    IdHttp.RecvBufferSize:=65534;
    IdHttp.Request.Accept:='text/html';
    IdHttp.ProxyParams.ProxyServer:=ProxyServer;
    IdHttp.ProxyParams.ProxyPort:=ProxyPort;
    QueryResult:=IdHttp.Get(QueryString);
    finally
    Synchronize(FComplete);
    IdHttp.DisconnectSocket;
    IdHttp.Free;
    end;
    end;

    procedure TDownloadThread.FComplete;
    begin
    if Assigned(FOnComplete) then FOnComplete(Self);
    end;
    Переменные, которые передаются в головной процесс, объявлены в секции public, так что при выполнении процедуры в головном процессе их видно.

    Я не претендую на звание хорошего программиста - меня этому не учили. Но работает же!

  15. #15

    Регистрация
    11.02.2005
    Авто
    2114
    Сообщений
    1 209
    Благодарности
    уже не помню, как Synchronize() устроен, но, думаю, что этого достаточно...

  16. #16
    AG Team Аватар для Vivos
    Регистрация
    04.07.2004
    Пол
    Пол: Мужской
    Сообщений
    6 435
    Благодарности
    Тут же напишу... Разрабатываю прогу для коммерческой разведки... Сейчас думаю над модулем поиска информацию по средством поисковиков... Как научить программу переходить по ссылкам??? И как обнаруживать нужную информацию на странице? Ссылки и текст? Программер из меня еще тот...

  17. #17
    AG Team Аватар для ScorpionSP
    Регистрация
    14.09.2006
    Пол
    Пол: Мужской
    Авто
    Ford Mondeo 2.3
    Возраст
    33
    Сообщений
    6 016
    Благодарности
    Цитата Сообщение от Nusferatus Посмотреть сообщение
    Их можно использовать даже при вызове хука из длл, хотя в таком случае гораздо сподручнее передавать любую структуру через Lparam.
    В С++ с этим осторожнее, тут есть грабли, связанные с пробросом STLных контейнеров в DLL.

    Цитата Сообщение от Nusferatus Посмотреть сообщение
    Матчасть по данной теме можно покурить на rzdn.ru. Там и форумы есть.
    Ну только rsnd.ru. Еще CodeProject и Google Groups рулят.

    Цитата Сообщение от Nusferatus Посмотреть сообщение
    ЗЫ. Дельфа дельфой, но win32 api никто не отменял
    +1.

  18. #18
    AG Team Аватар для ScorpionSP
    Регистрация
    14.09.2006
    Пол
    Пол: Мужской
    Авто
    Ford Mondeo 2.3
    Возраст
    33
    Сообщений
    6 016
    Благодарности
    Цитата Сообщение от Nusferatus Посмотреть сообщение
    +1
    Всё верно.
    Щас интереса ради залез в азбуку дельфей, поглазеть как там что реализовано с потоками)) Одно скажу ребята: C++ рулид!)))
    Всё-таки в таких вещах, что топикстартеру нужно додиез рулит.

  19. #19
    AG Team Аватар для ScorpionSP
    Регистрация
    14.09.2006
    Пол
    Пол: Мужской
    Авто
    Ford Mondeo 2.3
    Возраст
    33
    Сообщений
    6 016
    Благодарности
    Цитата Сообщение от Модуль Оверлеев Посмотреть сообщение
    рискну предположить, что твой OnComplete, в лучшем случае, свойство типа TNotifyEvent. или просто член класса. при завершении, поток вызывает этот делегат(сори за плюсовую терминологию), который, к примеру, добавляет в како-нить контейнер полученные данные. успешность этой операции сильно зависит от начального дезайна этой архитектуры. чтобы все работало без объектов синхронизации, можно было бы сделать примерно так(я почти не думал над этим, задача слишком обстрактная): какой-нить главный поток создает массив указателей на данные, к примеру с N ячейками. создает N потоков, указывая им, какие сайты они должны скачать, и в какие ячейки положить указатели на полученные данные. каждый рабочий поток, когда скачает, разместит в памяти, и сделает всю работу, записывает указатель в массив. главный поток спит (Sleep())циклически проверяя, что все ячейки массива перестали быть nil. когда они перестали, он обрабатывает эти данные, и потом освобождает память.
    недостатки этого подхода:
    1 - главный. можно гарантировать, что без синхронизации разложение (corruption) данных не произойдет, на 32-битной платформе Intel, где массив указателей выровнен на 4-байта. операция записи такого указателя будет атомарной.
    достоинства:
    1 - сомнительное. не использованы объекты синхронизации.

    короче, я бы так делать не стал. для винды существует очень быстрая и легковесная критическая секция, которая прекрасно синхрит потоки в одном процессе.
    Что-то тут по-мойму нужен WaitForMultipleObjects просто.
    Главное, в дедлок не загнать

  20. #20
    Аватар для SWW
    Регистрация
    14.11.2006
    Пол
    Пол: Мужской
    Сообщений
    193
    Благодарности
    А на профильных форумах не пробовал спрашивать? кывт например...

  21. #21
    Аватар для Stas_K
    Регистрация
    24.01.2006
    Пол
    Пол: Мужской
    Авто
    Chevrolet Cruze
    Возраст
    41
    Сообщений
    934
    Благодарности
    Цитата Сообщение от vivos Посмотреть сообщение
    Как научить программу переходить по ссылкам??? И как обнаруживать нужную информацию на странице? Ссылки и текст? Программер из меня еще тот...
    В Delphi знаю 3 варианта:
    - InternetAPI
    - Sockets
    - Компоненты Indy

    Есть еще TWebBrowser, но это уже будет через жо..

    Обнаруживать инфу по соответствующим тэгам в html-странице.

  22. #22
    AG Team Аватар для Vivos
    Регистрация
    04.07.2004
    Пол
    Пол: Мужской
    Сообщений
    6 435
    Благодарности
    Цитата Сообщение от Stas_K Посмотреть сообщение
    В Delphi знаю 3 варианта:
    - InternetAPI
    - Sockets
    - Компоненты Indy

    Есть еще TWebBrowser, но это уже будет через жо..

    Обнаруживать инфу по соответствующим тэгам в html-странице.
    Значит сейчас я делаю через жопу )))

    Есть ссылки где подробнее можно почитать?

  23. #23
    Аватар для Stas_K
    Регистрация
    24.01.2006
    Пол
    Пол: Мужской
    Авто
    Chevrolet Cruze
    Возраст
    41
    Сообщений
    934
    Благодарности
    Цитата Сообщение от vivos Посмотреть сообщение
    Есть ссылки где подробнее можно почитать?
    В любом поисковике куча информации.
    Вот тут много всего интересного: http://delphiworld.narod.ru/_internet_.html

  24. #24
    Аватар для Nusferatus
    Регистрация
    01.12.2006
    Пол
    Пол: Мужской
    Авто
    BMW m3
    Сообщений
    39 637
    Благодарности
    Цитата Сообщение от ScorpionSP Посмотреть сообщение
    Всё-таки в таких вещах, что топикстартеру нужно додиез рулит.
    Порекомендуй кстати литературу - давно хотел разобраться. Знаком с ним тока по описаниям, понравился пофигизм нащщёт типов.

    Цитата Сообщение от ScorpionSP Посмотреть сообщение
    В С++ с этим осторожнее, тут есть грабли, связанные с пробросом STLных контейнеров в DLL.
    Да эт не грабли, эт особенности, всё там просто и легко)

  25. #25
    Аватар для Nusferatus
    Регистрация
    01.12.2006
    Пол
    Пол: Мужской
    Авто
    BMW m3
    Сообщений
    39 637
    Благодарности
    Цитата Сообщение от vivos Посмотреть сообщение
    Значит сейчас я делаю через жопу )))

    Есть ссылки где подробнее можно почитать?
    Как ты это сейчас делаешь?

Страница 1 из 2 12 ПоследняяПоследняя
Похожие темы
  1. Нужна помощь.
    от 323 в разделе Полезно. Интересно. Познавательно
    Ответов: 8
    Последнее сообщение: 14.07.2005, 10:03
  2. Нужна помощь !
    от beco в разделе Автомобильный
    Ответов: 6
    Последнее сообщение: 28.06.2005, 22:27
  3. Нужна помощь
    от kadango в разделе Автомобильный
    Ответов: 13
    Последнее сообщение: 21.01.2005, 15:08
  4. Нужна помощь от людей в компутерах мыслящих!
    от Михаил ТРК в разделе Полезно. Интересно. Познавательно
    Ответов: 16
    Последнее сообщение: 11.01.2005, 09:17
  5. Срочно нужна помощь
    от slaer в разделе Автоправо
    Ответов: 3
    Последнее сообщение: 21.10.2004, 01:32
Ваши права
  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •