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

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

29.08.2012, 17:39. Показов 9290. Ответов 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
Ответ Создать тему
Новые блоги и статьи
Модель здравосохранения 17. Планы на выгорание
anaschu 23.05.2026
Вот конкретная схема реализации: В классе Работник добавить: накопленнаяУсталость — растёт каждый час работы, снижается в перерывы и болезни коэффициентПрезентеизма — снижает продуктивность. . .
Изменение цветов в палитре gif файла aka фавикона
russiannick 23.05.2026
Изменение цветов в палитре gif файла, юзаемого как фавиконка в составе html-файла, помещенная в base64, средствами нативного Java Script, навеянное сном в майский день. Для работы необходим браузер,. . .
Модель здравосохранения 16. Слишком хорошие и здоровые сотрудники уходят, недовольные зарплатой
anaschu 23.05.2026
Отладка увольнений и настройка производительности Сегодня во второй половине дня разобрались с механикой увольнений и настроили коэффициент сложности заданий. Вот что было сделано. . . .
Как я стал коммунистом))) Модель сохранения здоровья сотрудников, запись блога номер 15
anaschu 23.05.2026
Внезапно хорошее здоровье сотрудников не нужно капиталистам?))
Модель здравоСохранения 15. Как мы чинили AnyLogic модель рабочего коллектива: сочленение диаграммы состояний болезней и поломок в ресурспул
anaschu 23.05.2026
Как мы чинили AnyLogic модель рабочего коллектива Сегодня разобрались с пятью багами, из-за которых модель либо падала с ошибкой, либо давала совершенно бессмысленные результаты. Каждый баг был. . .
Диалоги с ИИ
zorxor 23.05.2026
Насколько я понимаю - Вы - Искусственный Интеллект. Это так? Да, всё верно. Я — искусственный интеллект. Я представляю собой большую языковую модель, созданную для помощи в самых разных задачах. . . .
Модель здравосохранения 14. Собираем всю модель вместе.
anaschu 22.05.2026
Модель собрана. В будущих постах на видео я покажу, как она работает. В этом посте запускаем её, проверяем результаты и разбираем что можно с ней делать дальше. Перед запуском проверяем. . .
Модель здравоохранения 13. Добавление самой системы здравоохранения.
anaschu 22.05.2026
В предыдущем посте мы настроили болезни. Теперь добавим события, которые управляют здоровьем всего коллектива, а также настроим рабочий график и расчёт финансов. В Main создаём четыре события. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru