Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.56/18: Рейтинг темы: голосов - 18, средняя оценка - 4.56
10 / 10 / 4
Регистрация: 12.10.2013
Сообщений: 249

Отображения на форме текстового сообщения с информацией о ходе расчета в отдельном потоке

15.08.2014, 20:50. Показов 3446. Ответов 32
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Делаю программу, которая занимается вычислениями. Вычислений много и если их не вынести в отдельный поток, то программа выглядит подвисшей, пока вычисления не закончатся. Ниже код в сокращенном виде.
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
class TMyThread: public TThread
{
    protected:
        void __fastcall Execute();
 
    private:
        void __fastcall NewCaption();
        UnicodeString CurrentAction;
};
 
void __fastcall TMyThread::Execute()
{
    int it = -1;
    do
    {
        it++;
        CurrentAction = "Итерация " + IntToStr(it+1) + "...";
        Synchronize(NewCaption);
    }
    while (it < 100000);
}
 
void __fastcall TMyThread::NewCaption()
{
    Form1->Label1->Caption = CurrentAction;
}
В таком варианте на главной форме не отображаются промежуточный отметки. Только по окончании цикла появляется последняя запись. Если функцию NewCaption() модифицировать так:

C++
1
2
3
4
5
void __fastcall TMyThread::NewCaption()
{
    Form1->Label1->Caption = CurrentAction;
    Application->ProcessMessages();
}
то все отображается как надо, но у меня сомнения в уместности использования здесь ProcessMessages(). Можно решить вопрос без этой функции?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
15.08.2014, 20:50
Ответы с готовыми решениями:

TIdHTTP в отдельном потоке и прогресс бар на основной форме
У меня есть TIdHTTP (upd) в отдельном потоке и надо отобразить хот загрузки файла на основной форме. Все бы хорошо, но значение...

Вывод сообщения в отдельном окне с информацией
Знающие люди подскажите пожалуйста. Нужен батник для вывода сообщения с информацией в отдельном окне как на первом скриншоте ...

Создать приложение, в отдельном потоке вычисляющее значение w и непрерывно обновляющее его в потоке
Ребят, с потоками не работал не когда. Есть задание , я понимаю что хотят, а вот как сделать потоками хз . Создайте приложение, в...

32
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33372 / 21498 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
15.08.2014, 21:23
Что характерно - без ProcessMessages прекрасно показывает ход цикла. Проверяй на чистом проекте...
0
10 / 10 / 4
Регистрация: 12.10.2013
Сообщений: 249
15.08.2014, 22:35  [ТС]
На чистом проекте пробовал - действительно работает. Не пойму почему в текущем проекте не получается. Я перечислю особенности использования отдельного потока у меня, а вы посмотрите, может как раз причину найдете.

1. Экземпляр класса потока у меня создается вместе с приложением и является членом класса формы. Память освобождается при уничтожении формы.
2. Метод Execute() активируется нажатием на кнопку. За время работы программы метод Execute() можно вызвать любое количество раз. Там выполняются вычисления, которые зависят от исходных данных, задаваемых пользователем через элементы управления на форме.
3. Само вычисление и вызов функции Synchronize(NewCaption) находятся не в Execute(), а в отдельной расчетной функции (член класса потока), которая вызывается как раз из Execute().

Не знаю что еще могло бы мешать корректной работе программы.
0
1408 / 572 / 127
Регистрация: 31.10.2011
Сообщений: 1,960
16.08.2014, 01:42
Нитонисе, зачем в процессе ProcessMessages ?
0
10 / 10 / 4
Регистрация: 12.10.2013
Сообщений: 249
16.08.2014, 12:02  [ТС]
Цитата Сообщение от _Dimon_ Посмотреть сообщение
зачем в процессе ProcessMessages ?
Чтобы обработать все сообщения немедленно.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33372 / 21498 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
16.08.2014, 12:20
Нитонисе, сделай минимальный тестовый проект, повторяющий описанное тобой поведение, и прикрепи его в виде архива. По описанию трудно разобраться, "кто на ком стоял" (С)
0
10 / 10 / 4
Регистрация: 12.10.2013
Сообщений: 249
16.08.2014, 14:48  [ТС]
Цитата Сообщение от UI Посмотреть сообщение
сделай минимальный тестовый проект, повторяющий описанное тобой поведение, и прикрепи его в виде архива
Воспроизвел структуру своей программы в тестовом простом проекте. Описанная мной проблема присутствует.
Вложения
Тип файла: zip Поток.zip (78.1 Кб, 12 просмотров)
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33372 / 21498 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
16.08.2014, 15:58
Лучший ответ Сообщение было отмечено Нитонисе как решение

Решение

Нитонисе, не надо вызывать метод Execute() напрямую, просто переведи поток из "спящего" состояния в рабочее через
C++
1
MyThread->Start();
, и проблема тут же исчезает...

А еще интереснее - вот так...

Поток:
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
30
31
32
33
34
35
36
37
38
__fastcall TMyThread::TMyThread(bool CreateSuspended) : TThread(CreateSuspended)
{
    FreeOnTerminate = false;
    FSuspended = true; // публичное поле bool FSuspended в классе потока
}
 
// ---------------------------------------------------------------------------
void __fastcall TMyThread::Execute()
{
    do
    {
        if (!FSuspended)
        {
            FSuspended = true; // Переводим в состояние "ожидания"
            DoCalculate();  // Отработал один цикл, и снова жди
        }
        else Sleep(1); // Чтобы ресурсы не жрал...
    }
    while (!Terminated);
}
 
// ---------------------------------------------------------------------------
void __fastcall TMyThread::NewCaption()
{
    Form1->Label1->Caption = Msg;
}
 
void __fastcall TMyThread::DoCalculate()
{
    int i = 0;
    do
    {
        i++;
        Msg = L"Итерация " + IntToStr(i) + L"...";
        Synchronize(NewCaption);
    }
    while (i < 10000);
}
Вызов:
C++
1
2
3
4
5
6
7
8
9
10
11
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    MyThread = new TMyThread(false);
}
 
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    // MyThread->Calculate();
    MyThread->FSuspended = false; // "разморозил" поток, он отработал один цикл и снова "уснул"
}
2
10 / 10 / 4
Регистрация: 12.10.2013
Сообщений: 249
16.08.2014, 16:29  [ТС]
Цитата Сообщение от UI Посмотреть сообщение
не надо вызывать метод Execute() напрямую
Вот жеж как. Сам бы не догадался Спасибо за подсказку. А по поводу FSuspended - что-то мне не понравился способ. Ведь это фактически Execute() выполняется постоянно, только не входит в цикл, пока FSuspended = true.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33372 / 21498 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
16.08.2014, 17:27
А ничего, что поток работает только до тех пор, пока выполняется Execute? На том все и построено. Закончился Execute - кирдык, поток завершен. Чтобы иметь возможность несколько раз выполнять действия, описанные в Execute, неоднократно, тебе в любом случае придется делать цикл.
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
16.08.2014, 20:38
Цитата Сообщение от UI Посмотреть сообщение
FSuspended = true; // публичное поле bool FSuspended в классе потока
С каких пор оно стало публичным?

Добавлено через 1 минуту
C++
1
2
3
4
5
6
7
8
9
10
   do
    {
        if (!FSuspended)
        {
            FSuspended = true; // Переводим в состояние "ожидания"
            DoCalculate();  // Отработал один цикл, и снова жди
        }
        else Sleep(1); // Чтобы ресурсы не жрал...
    }
    while (!Terminated);
Чет я не понял таких маневров...
0
10 / 10 / 4
Регистрация: 12.10.2013
Сообщений: 249
18.08.2014, 16:29  [ТС]
Цитата Сообщение от UI Посмотреть сообщение
не надо вызывать метод Execute() напрямую
Тут проблема образовалась. Повторная попытка активации потока вызывает ошибку: Cannot call Start on a running or suspended thread. После выполнения Execute поток же находится в статусе suspended? И как тогда повторно запустить Execute?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33372 / 21498 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
18.08.2014, 17:13
Ты ж не читаешь то, что тебе пишут. Так я просто не буду писать. Смысл в чем? Опять распинаться, объяснять что-то, чтобы ты опять сделал по-своему, а потом причитал, что "ничего не работает"? Я написал все в предыдущих двух постах. Умеешь читать - читай. Не умеешь - ничего, дворники тоже нужны.
0
10 / 10 / 4
Регистрация: 12.10.2013
Сообщений: 249
18.08.2014, 20:06  [ТС]
Вы про FSuspended? Из вашего предыдущего поста не ясно, что замену Execute на Start нужно использовать совместно с FSuspended. Я так подумал, что это альтернатива или необязательное дополнение. Получается на поток извне я могу воздействовать только изменением FSuspended на false. То есть внутри потока постоянно идет проверка этого свойства. Неужели нет способа, когда поток был бы в режиме ожидания, без ежесекундных внутренних проверок, активировался строго по запросу?..
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
18.08.2014, 20:29
Цитата Сообщение от Нитонисе Посмотреть сообщение
Неужели нет способа, когда поток был бы в режиме ожидания, без ежесекундных внутренних проверок, активировался строго по запросу?..
Ну мне не нравится решение в виде вытаскивания FSuspended, для это есть объекты события типа TSimpleEvent, ну и еще можно как вариант организовать очередь сообщений в потоке.
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
19.08.2014, 10:48

Не по теме:

Цитата Сообщение от UI Посмотреть сообщение
Чтобы иметь возможность несколько раз выполнять действия, описанные в Execute, неоднократно, тебе в любом случае придется делать цикл.
goto в конце Execute в начало. Курица не птица, goto не цикл, все дела. :p



Цитата Сообщение от UI Посмотреть сообщение
C++
17
else Sleep(1); // Чтобы ресурсы не жрал...
Как на счет Sleep(0)?
И зачем FreeOnTerminate выставлено в false?

Цитата Сообщение от Avazart Посмотреть сообщение
С каких пор оно стало публичным?
Наверное потому, что объявлено в public секции потока.

Цитата Сообщение от Avazart Посмотреть сообщение
организовать очередь сообщений в потоке
А как вот на счет такого варианта:
C++
1
2
3
4
5
6
7
8
9
10
void __fastcall TSaveFileThread::Execute()
{
  while( !this->Terminated )
    {
    ResetEvent( hThreadDoneEvent );
    /*Полезный код*/
    SetEvent( hThreadDoneEvent );
    this->Suspend();
    }
}
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33372 / 21498 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
19.08.2014, 11:26
Цитата Сообщение от SatanaXIII Посмотреть сообщение
А как вот на счет такого варианта:
Я бы Suspend-ом вообще не пользовался, разве что для отладки. Но уж не в окончательном варианте приложения - это точно. Для меня всё, что помечено как deprecated - табу.
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
19.08.2014, 11:56
UI, ясно. А что на счет вот этих двух:
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Как на счет Sleep(0)?
И зачем FreeOnTerminate выставлено в false?
0
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
19.08.2014, 12:18
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Наверное потому, что объявлено в public секции потока.
Каким чудом? Оно либо private либо protected
http://docwiki.embarcadero.com... .Suspended

Добавлено через 17 минут
Цитата Сообщение от SatanaXIII Посмотреть сообщение
C++
1
this->Suspend();
Зачем, если эвент можно ждать WaitForSingleObject() ?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33372 / 21498 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 12
19.08.2014, 12:19
Avazart, ты код читал? Или просто бегло просматривал?
// публичное поле bool FSuspended в классе потока
видел? НИКАКОГО отношения к свойствам/полям класса TThread, это мое поле, собственное, хочу - называю его FSuspended, хочу - SuperPuperSuspended. Блин, если тебе так не нравится имя - поменяй его на FAvazartSuspended... В чем проблема-то? Лишь бы что-то сказать? Если у тебя в блоге чего-то нет - это неправильно?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
19.08.2014, 12:19
Помогаю со студенческими работами здесь

GDI+. Почему в отдельном потоке картинки сохраняются как белые прямоугольники, а в основном потоке - всё Ок?
Всем привет, делаю функцию уменьшения картинок при помощи библиотеки GDI+, в отдельном потоке происходит уменьшение картинки и её...

Класс в отдельном потоке
Привет. Мне нужно, чтобы класс выполнялся в отдельном потоке. #include &lt;iostream&gt; #include &lt;thread&gt; #include...

QGraphicsScene в отдельном потоке
Доброе утро. Подскажите пожалуйста.Всего три потока: Гуи, Идет прием UDP, обработка . Принимаются множество &quot;пакетов&quot; и из...

Форма в отдельном потоке
Привет, есть 3 формы (грубо говоря две) одну надо запустить в отдельный поток. Form1 С нее происходит запуск формы по нажатию кнопки. ...

Запросы к БД в отдельном потоке
Всем привет! Хочу спросить специалистов и просто опытных людей. Делаю приложение winForms. Приложение будет отображать результаты...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит: токи, напряжения и их 1 и 2 производные при t = 0;. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru