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

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

29.08.2012, 17:39. Показов 9508. Ответов 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
8489 / 6156 / 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
8489 / 6156 / 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
8489 / 6156 / 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
8489 / 6156 / 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
8489 / 6156 / 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
8489 / 6156 / 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
8489 / 6156 / 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
8489 / 6156 / 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
8489 / 6156 / 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
8489 / 6156 / 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
Ответ Создать тему
Новые блоги и статьи
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru