Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  04:27[Войти] | [Зарегистрироваться]
Ответ на вопрос № 83687

23-10-2019 11:08
Всего доброго.

Вот хотел проконсультироваться насчет следующей задачи.
Имеется некая процедура, в теле которой вызывается другая процедура, которая работает в отдельном потоке.
Для того чтобы не зависал гуй. Т.е. мне надо дождаться окончания работы потока и продолжить код главного потока.
Начал делать на TEvent, но не понравилось мне это и реализовал так:
...
Thread.Start;
while not Thread.IsOk do
           begin
           Application.ProcessMessages;
           end;
IsOk - это свойство потока, которое устанавливается в true, когда завершается Execute
Вроде всё работает, но опять не нравится мне это.
Вот и хочу спросить: как поступать правильно?

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

27-10-2019 10:00 | Сообщение от автора вопроса
Спасибо всем.
Первый вариант отдал в работу, но начал делать "правильную" версию. Обязательно учту Ваши замечания.

27-10-2019 02:01
Получается примерно такая картина: поток нужен исключительно для того, чтобы можно было двигать форму приложения, но на неё всё-равно нажать ничего нельзя (включая кнопку: "Я передумал качать этих интернов через GPRS в роуминге, можно отменить?") Если так - то предлагаю переделать немного визуальную часть приложения. Нажатие на кнопку должно запускать поток, но менять название кнопки с "Начать закачку" (например! может быть и "Начать расчёт") на "Прервать закачку" (соответственно, "Остановить расчёт, потеряв данные").
При нажатии кнопки нужно проверять состояние запущенности потока: либо то, что Thread<>nil, либо Caption кнопки (худшее из всех вариантов), либо Tag кнопки, либо какой-то отдельный флаг. Соответственно, нажатие кнопки, когда процесс НЕ запущен просто запускает поток на исполнение (возможно, инициализирует поток, или что-то такое). Это не займёт много времени, скорее всего, пользователь даже не заметит, что что-то произошло (кроме смены Caption кнопки), но для верочки можно выполнить такой финт ушками:

Screen.Cursor:=crHourglass;
try
  .. // ваш код по запуску/завершению потока
finally
  Screen.Cursor:=crDefault;
end;


Финт заключается в том, что курсор-часики будет "крутиться" даже если ваше приложение в принципе зависло, он крутится силами самой ОС, а не вашего приложения.
Приём сообщения от потока о нормальном завершении приведёт к тому, что кнопка переименуется штатно обратно в "Начать закачку", поток штатно завершится и все флаги (заголовок, Tag кнопки, Thread:=nil, или ещё какой-то флаг) будут сняты, приготовив программу к новой итерации.
Если же в нажатии кнопки выяснится, что поток запущен, то надо ему послать сообщение: "Надо помереть" и выполнить WaitFor (если потоки выполнены не на базе TThread и вы пользуетесь Windows - то WaitForSingleObject). В данном случае - согласен, интерфейс "заморозится" на некоторое время, но тут ничего и не сделаешь нормально, только ранее описанный финт ушами. Я думаю, такое решение вас должно устроить. WaitFor... должен подождать некоторое разумное время (я обычно ставлю 3...30 секунд, в зависимости от задачи), после чего (если не дождался) - выполнить TerminateThread и доложить пользователю. Разумеется, при любом раскладе, надо также, как и при нормальном завершении потока снять флаги и поменять Caption кнопарика.
Хотя если хочется сложностей - можно сделать флаг не булевый, а целочисленный (тогда - либо Tag, либо внешний флаг), тогда можно будет по второму нажатию кнопки перевести её в состояние "Завершаемся... подождите..." В этом случае, WaitFor... мы не используем, поток сам доложит через сообщение в основную программу о том, что произошло. И вновь может оказаться, что поток сам не завершается. В этом случае, если кнопка прожимается в состоянии "Ждём завершения потока", надо будет выполнить TerminateThread... ну и далее - как в предыдущем пункте. Хотя есть вариант дать пользователю кнопку "Возобновить процесс". Этот вариант требует самого аккуратного программирования, так как количество состояний данного "конечного автомата" уже четыре, да ещё и синхронизация с дочерним потоком...

25-10-2019 12:33
>>>как мне дождаться завершения потока?
Так я же написал. Запускаем поток и возвращаемся. Чтобы пользователь не тыкал куда не надо, вешаем форму-заглушку ожидания с какой-нибудь крутилкой, запрещаем формы/контролы, ждем от потока сообщения о завершении. Потом все размораживаем.
>>>То же самое с ожиданием вставки флэшки. Хотя, это можно было бы вставить в модальное окно, но испортило бы задуманный интерфейс приложения.
Модальное окно и есть верный вариант. Но можно и основное окно заморозить (Enabled:=false), показав в интерфейсе какое-то напоминание. Но вообще если пользователь по ходу процесса должен вводить какие-то данные, то напрашивается что-то вроде визарда

24-10-2019 15:02 | Сообщение от автора вопроса
Хотел добавить, что в этой же проге возникла похожая задача. Потребовалось вставить в "прямоленейный код" выбор данных из Combobox. Опять цикл с ProcessMessages и проверкой совершения выбора? То же самое с ожиданием вставки флэшки. Хотя, это можно было бы вставить в модальное окно, но испортило бы задуманный интерфейс приложения.

24-10-2019 14:56 | Сообщение от автора вопроса
Спасибо. Конечно, уже написано миллион статей про это. Но тут получилось, что в готовый код пришлось встраивать многопоточность в очень срочном порядке. Сам код - это, как бы последовательность команд. Какие-то команды выполняются в отдельных нитях (чтобы не висло главное окно). Т.е. вызвал процедуру и нужно ждать её завершения. При этом окно прорисовывается при перекрытии. Контролов минимум и вроде всё блокирую, чтобы не нажать и не создать лапшу. ProcessMessages сам считаю злом, поэтому и написал.
Но вот в данном случае, чтобы не переписывать всю программу, как мне дождаться завершения потока? Даже если посылать сообщения, то они будут обрабатываться в одном месте, а выполнение надо остановить в другом. Цикл без ProcessMessages? Но тогда окно не прорисовывается.
Короче, нехорошо написал, но переделать нет возможности. :(

24-10-2019 10:17
Избегайте ProcessMessages. Захочется приложению закрыться в этом цикле, что будете делать?
Пусть поток пошлет сообщение главному окну (через PostMessage) о том, что он завершил свои дела. Так что после старта потока просто возвращайтесь к основной работе

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Зимой — белый, летом — серый. Кто?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования