Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.68/47: Рейтинг темы: голосов - 47, средняя оценка - 4.68
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128

IdHTTP->Get в потоке и прогрессом

29.08.2012, 17:39. Показов 9121. Ответов 45
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
TIdHTTP *HTTP = new TIdHTTP(NULL);
    if (HTTP) {
        try {
            HTTP->ConnectTimeout = 10000;
            HTTP->ReadTimeout = 10000;
            if (HTTP->Connected()) HTTP->Disconnect();
            html = HTTP->Get("http://checkip.dyndns.com/");
        }
        catch (...) {} //Соединение не установлено
        try {HTTP->Socket->Close();}
        catch (...) {HTTP->Disconnect();}
        delete HTTP;
        HTTP = NULL;
    }
Хочу засунуть его в поток, получаем
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
String html;
 
void __fastcall Th::Execute()
{
    int p1, p2;
    TIdHTTP *HTTP = new TIdHTTP(NULL);
    if (HTTP) {
        try {
            HTTP->ConnectTimeout = 10000;
            HTTP->ReadTimeout = 10000;
            if (HTTP->Connected()) HTTP->Disconnect();
            html = HTTP->Get("http://checkip.dyndns.com/");
        }
        catch (...) {} //Соединение не установлено
        try {HTTP->Socket->Close();}
        catch (...) {HTTP->Disconnect();}
        delete HTTP;
        HTTP = NULL;
    }
    p1 = html.Pos("Address:")+9;
    p2 = html.Pos("</body>");
    html = html.SubString(p1,p2-p1);
    Synchronize(&UpdateMemo);
}
 
void __fastcall Th::UpdateMemo()
{
        Form1->Memo1->Lines->Add("WAN IP: " + html);
}
Вроде работает, но как сделать прогресс? На форме это делалось добавлением TIdHTTP на форму и там в Event'ах выставлялись функции... А вот в потоке как их создать я не догнал... ?
Пример Event'ов для IdHTTP из формы
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//---------------------------------------------------------------------------
void __fastcall TForm1::work(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCount)
{
    Form1->Memo1->Lines->Add(AWorkCount);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::workBegin(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCountMax)
{
 
}
//---------------------------------------------------------------------------
void __fastcall TForm1::workEnd(TObject *ASender, TWorkMode AWorkMode)
{
 
}
//---------------------------------------------------------------------------
//В Unit1.h:
void __fastcall work(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCount);
void __fastcall workBegin(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCountMax);
void __fastcall workEnd(TObject *ASender, TWorkMode AWorkMode);


И пару вопросов по потокам:
  • String html пришлось сделать глобальной - есть ли другие варианты для передачи в Synchronize()?
  • Если я из потока вызываю функцию, которая написана в Unit1 (т.е. она не относится к потоку) - она же будет потом работать в этом потоке? (главное убрать из функции контакт с формой?)
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.08.2012, 17:39
Ответы с готовыми решениями:

Как ускорить чтение с прогрессом в потоке
Есть класс Reader который читает содержимое файлов в DataTable. Но есть проблема. Если мы Дергаем делегат прогресса из цикла чтения то это...

Отправка вайла в потоке idhttp
Ребят, загрузчик файлов на сервер через idhttp + idmultipartformdata работает на ура. Но есть проблема - нужно сделать загрузку в...

idhttp в потоке получает пустой txt файл
Доброго времени суток. Пишу обновлялку для программы. Собственно, если код вставлен в FormCreate - все работает. Если же вставить в...

45
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
31.08.2012, 19:17
Студворк — интернет-сервис помощи студентам
Т.е. если я сделаю по вашему примеру в Потоке FreeOnTerminate = true; мне больше ни о чем беспокоится не стоит? конечно, кроме момента повторного нажатия кнопки, тут уже надо будет сделать, что-то типа
Ну да...

Если не ошибаюсь я просто блокировал кнопку пока чтоб ее нельзя было нажать повторно пока поток не завершится.

C++
1
if (Thread) Thread->Terminate();
Не надежно по тому что после завершеня работы указатель на поток не обнуляется

Добавлено через 2 минуты
Определить состояние потока TThread
1
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128
31.08.2012, 19:53  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
C++
1
if (Thread) Thread->Terminate();
Не надежно по тому что после завершеня работы указатель на поток не обнуляется
Почему это? Это равносильно обычному завершению потока.
Вот Архангельский пишет:
C++
1
2
3
4
5
6
7
8
void __fastcall T::Execute()
{
    do
    {
        ...
    }
    while (!Terminated);
}
Метод Terminate обеспечивает "мягкое" завершение потока.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
31.08.2012, 19:55
То что я говорил каcается
C++
1
if (Thread) //....
0
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128
31.08.2012, 20:27  [ТС]
Если поток не обнуляет указатель даже когда сам завершается, значит мне это и не надо...полагаю

Добавлено через 26 секунд
Цитата Сообщение от Avazart Посмотреть сообщение
То что я говорил каcается
C++
1
if (Thread) //....
А я понял, вы говорите что я не проверю закончился он или нет, ясно...

Добавлено через 11 минут
Тащем-то прочитав 5 страниц, где вы пытались переспорить друг друга , я сделал вывод, что надо отказаться от FreeOnTerminate и делать удаление и обнуление самому, тогда if (Thread) будет работать. Верно?

Добавлено через 11 минут
Нет не верно, я какую-то чушь сказал...потому что я не узнаю когда мне надо удалить вручную.

Добавлено через 6 минут
Я же могу банально сделать глобальный флаг (bool dead), которому поток по завершении будет присваивать тру и если этот флаг=тру, то поток умер... вот и решение! Не согласны?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
31.08.2012, 20:53
Нет...

Разве что синхронизировав её...

Нужно ли синхронизировать доступ к переменной из двух потоков?

Добавлено через 4 минуты
Тащем-то прочитав 5 страниц, где вы пытались переспорить друг друга , я сделал вывод, что надо отказаться от FreeOnTerminate и делать удаление и обнуление самому, тогда if (Thread) будет работать. Верно?
Все зависит от алгоритма программы в целом...
1
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128
31.08.2012, 21:30  [ТС]
Даа, потоки оказались геморной темой
В общем, спасибо, буду использовать пример "UI" в вашей переработке:
C++
1
2
3
4
    DWORD Code;
    if (!GetExitCodeThread(hThread,&Code)) Memo1->Lines->Add("Error!");
    else if (Code == STILL_ACTIVE) Memo1->Lines->Add("Still active!");
    else Memo1->Lines->Add("Terminated");
и не изобретать квадратные колеса на велосипед.

Но немного не понятно, когда он выдаст Terminated? Если будет TreminateThread без освобождения памяти?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
31.08.2012, 21:38
Ну TThread это лиш класс обвертка потока WinApi поэтому надо отталкиваться от сюда...

А вы собираетсь применять TerminateThread() ? -это грубый способ...

Но немного не понятно, когда он выдаст Terminated?
Если вы закончите поток ->Terminate() или он Finished()

Добавлено через 2 минуты
This function returns immediately. If the specified thread has not terminated and the function succeeds, the status returned is STILL_ACTIVE. If the thread has terminated and the function succeeds, the status returned is one of the following values:

The exit value specified in the ExitThread or TerminateThread function.

The return value from the thread function.

The exit value of the thread's process.
http://msdn.microsoft.com/en-u... s.85).aspx
0
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128
31.08.2012, 21:40  [ТС]
Кстати, я сделал MyThread->Terminate(); и поток завершился, при том, что в потоке не было проверки на Terminated... выходит это не обязательно? 0_о тогда зачем Архангельский писал
C++
1
2
3
4
5
6
7
8
void __fastcall T::Execute()
{
    do
    {
        ...
    }
    while (!Terminated);
}
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
31.08.2012, 21:44
Для мягкого завершения... если вычисления циклические...

Terminate() устанавливает Terminated= true; поэтому цикл прекращается и поток заканчивается дойдя до условия while, "логически" завершенным.
0
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128
31.08.2012, 21:46  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
А вы собираетсь применять TerminateThread() ? -это грубый способ...
Не собираюсь! Он еще и опасный...

Цитата Сообщение от Avazart Посмотреть сообщение
Если вы закончите поток ->Terminate() или он Finished()
Если я заканчиваю поток (сам по себе или Terminate(); ), он пишет Error, в процессе пишет Still Active, если сделать TerminateThread пишет Terminated... поэтому и спросил, мне показалось это странным...

Добавлено через 1 минуту
Мой поток
C++
1
2
3
4
5
6
7
8
9
10
11
void __fastcall ThreadHTTP::Execute()
{
    ///
    int i;
    while (i!=1000) {
    i++;
    Sleep(1000);
    Synchronize(&UpdateCaption);
    }
    ///
}
Terminate() его вырубает сразу, хотя в потоке проверки на Terminated нет
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
31.08.2012, 21:50
Если я заканчиваю поток (сам по себе или Terminate(); ), он пишет Error, в процессе пишет Still Active, если сделать TerminateThread пишет Terminated... поэтому и спросил, мне показалось это странным...
Ну я там не помню что за код выкладывал... может он там не совсем корректнный...
Если подумать то можно доработать...

Добавлено через 3 минуты
Terminate() его вырубает сразу, хотя в потоке проверки на Terminated нет
Не должен..
0
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128
31.08.2012, 21:51  [ТС]
Это если я вызываю Terminate сразу после запуска потока - он завершается.
C++
1
2
    T_HTTP->Resume();
    T_HTTP->Terminate();
Если вызываю Terminate с другой кнопки, все ок, ничего не происходит...
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
31.08.2012, 21:57
Ну так может где-то есть еще внутри условие,еще до Execute();

C++
1
2
3
4
5
6
7
8
9
10
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TMyThread* Thread1 = new TMyThread(true);
 
Thread1->Resume();
Sleep(1000);
Thread1->Terminate();
}
//---------------------------------------------------------------------------
0
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128
31.08.2012, 22:15  [ТС]
Проверка на состояние потока TThread

Код от "UI":
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
DWORD ec = 0;
      if(hThread && GetExitCodeThread(hThread,&ec) && (ec == STILL_ACTIVE))
      {
            if (T_HTTP->Finished)
            {
                  ShowMessage("Thread is finished!"); // После завершения поток самоудалится, поэтому сюда никогда не придем
            }
            else if (T_HTTP->Terminated)
            {
                  ShowMessage("Thread is terminated!"); // Это неверная диагностика. У потока _запросили_ завершение
            }
            else
            {
                  ShowMessage("Thread is working!"); // Поток работает
            }
      }
      else
      {
            // Поток завершен и удален автоматически, сбрасываем хендл в 0
            //(или он еще не был инициализирован, хендл и так нулевой)
            ShowMessage("Thread is not initialized!");
            hThread = 0;
      }
Ваш код:
C++
1
2
3
4
5
DWORD Code;
if(!GetExitCodeThread(hThread,&Code)) ShowMessage("Error!");
else
 if(Code== STILL_ACTIVE) ShowMessage("Still active!");
 else ShowMessage("Terminated");
Переделал на так:
C++
1
2
3
    DWORD Code;
    if (GetExitCodeThread(hThread,&Code) && (Code == STILL_ACTIVE)) Memo1->Lines->Add("Still active!");
    else Memo1->Lines->Add("Terminated");
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
31.08.2012, 22:16
Да еще до наступления Execute в самом классе потока может быть где то внутри спрятано условие...например в конструкторе...
0
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128
31.08.2012, 22:29  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
Да еще до наступления Execute в самом классе потока может быть где то внутри спрятано условие...например в конструкторе...
Угу, наверно.

PS: Resume/Suspend не рекомендованы к использованию...
http://docwiki.embarcadero.com... ead.Resume

Для только что созданного потока Resume() надо заменять Start();
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
31.08.2012, 22:32
Для только что созданного потока Resume() надо заменять Start();
У меня 2009 Builder там такого еще нет...

А что вместо Suspend ?
0
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128
31.08.2012, 22:39  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
У меня 2009 Builder там такого еще нет...

А что вместо Suspend ?
Они это сделали в 2010 году, поэтому и нет. Это связано с тем, что Суспенд может вызвать дедлоки и т.п.
Вместо него рекомендуют использовать TEvent и TMutex.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
31.08.2012, 22:42
Это связано с тем, что Суспенд может вызвать дедлоки и т.п.
Об этом не знал...

Вместо него рекомендуют использовать TEvent и TMutex.
Ну это аналоги WinApi, как я понимаю... , есть еще TCriticalSection
0
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128
31.08.2012, 22:59  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
Ну это аналоги WinApi, как я понимаю... , есть еще TCriticalSection
Походу.

Еще есть бесплатная библиотека OmniThreadLibrary, но она написана на Делфи и я не знаю канает ли она для C++. Судя по этому посту http://www.thedelphigeek.com/2... s-you.html автор ее компилировал для С++... Скачать можно тут http://code.google.com/p/omnithreadlibrary/
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
31.08.2012, 22:59
Помогаю со студенческими работами здесь

Отправка картинки IdHTTP POST в потоке TMemoryStream
Получаю я картинку(капча) в поток(TMemoryStream) посредством запроса. Потом мне нужно эту картинку отправить на сервис, вот тут я...

IdHTTP и IdHTTP сервер: как отправить сообщение от сервера к клиенту?
Всем привет, отправляю файл по частям с клиента на сервер, и хочу получать обратное сообщение, что текущая часть файла дошла успешно....

Скачивание файла с прогрессом
Привет. Есть на HTTP сервере файл &gt; 10 MB надо его скачать. URL url = new URL(...); File file = new File(getApplicationDir(),...

Очистка папки с прогрессом
Очистка папки с прогрессом. Здравствуйте! Необходимо сделать так что-бы при очистке какой-либо папки был прогресс выполнения данной...

Скачивание файла с прогрессом
Ставлю на загрузку файл. Хочу чтобы отображался прогресс скачивания. Программа тупо зависает до момента окончания скачивания private...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru