Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.10.2011, 18:36   #1
bratcho
Пользователь
 
Регистрация: 14.10.2011
Сообщений: 20
По умолчанию Таймеры и модальные окна

Всем привет! Ребят подскажите пожалуйста!
Суть проблемы в следующем.
Есть у меня таймер на главной форме, назначение его - периодический опрос регистров контроллера и отображение данных. Смысл в том что когда я вызываю модальное окно (ShowModal) таймер свое выполнение иногда (не всегда но иногда) прерывает! Подскажите пожалуйста как решить эту проблему?

(Вместо таймера использовал поток, но потом от него отказался, так как иногда по непонятным причинам выполнение потока прерывается)
Заранее спасибо!
bratcho вне форума Ответить с цитированием
Старый 26.10.2011, 19:05   #2
FaTaL
Участник клуба
 
Аватар для FaTaL
 
Регистрация: 09.11.2007
Сообщений: 1,761
По умолчанию

Модальное окно всегда прерывает основной поток. Зачем Вам модальное окно? Отсюда копать надо.
FaTaL вне форума Ответить с цитированием
Старый 26.10.2011, 19:10   #3
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
таймер свое выполнение иногда (не всегда но иногда) прерывает!
Цитата:
но потом от него отказался, так как иногда по непонятным причинам выполнение потока прерывается)
думаю это одна и та же проблема. криво написанный код или кривой алгоритм обработки.
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 02.12.2011, 15:09   #4
bratcho
Пользователь
 
Регистрация: 14.10.2011
Сообщений: 20
По умолчанию

В общем с кодом разобрался, действительно внутри кода были ошибки и поэтому и таймер и поток свое выполнение прекращал. В итоге остановился на потоке.
По поводу окон - у меня в приложении есть так сказать каскадный вызов окон. На экране могут быть одновременно показано до 3-х форм, то есть главная форма программы вызывает вторую форму, а вторая форма вызывает третью, причем необходимо чтобы при вызове очередного окна предыдущие были недоступны, как это реализовать не используя модальные окна я не знаю, может кто подскажет?
И более того появилась опять проблема...
Поток считывания регистров ПЛК должен выполняться постоянно и осуществлять опрос регистров с заданной периодичностью(задержку между вып-ем считывания внутри потока реализовал посредством sleep), но при вызове модального окна во время выполнения процедуры считывания внутри потока поток свое выполнение приостанавливает ((. И возобновляет свое выполнение только после закрытия модального окна. Может кто подскажет в чем проблема?
bratcho вне форума Ответить с цитированием
Старый 02.12.2011, 15:19   #5
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
но при вызове модального окна во время выполнения процедуры считывания внутри потока поток свое выполнение приостанавливает ((. И возобновляет свое выполнение только после закрытия модального окна.
Все в полном соответствии с описанием showModal.
выполнение процедуры остановлено и ждет ответа пользователя.
вывод НЕ ИСПОЛЬЗОВАТЬ внутри потока ShowModal.
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 02.12.2011, 16:44   #6
bratcho
Пользователь
 
Регистрация: 14.10.2011
Сообщений: 20
По умолчанию

Так все бы нормально, и я понимаю что внутри потока ShowModal выполнение потока до закрытия модального окна прерывает. Модальное окно вызывается НЕ ВНУТРИ ПОТОКА. Поток опроса у меня никаких модальных окон не вызывает. А просто при вызове модального окна из любой формы поток свое выполнение приостанавливает, причем что самое интересное если модальное окно вызвано не во время выполнения процедуры опроса потока, а во время ожидания (sleep - реализованного внутри потока), то все нормуль, поток свое выполнение не приостанавливает, и поток выполняется дальше и выполняет периодический опрос с заданной частотой, а если мы модальное окно вызовем во время процедуры опроса, то выполнение приостанавливается.
Я может до этого проблему не полностью описал, но есть еще вот что...
Та самая процедура опроса, во время которой из-за модальных окон поток свое выполнение и приостанавливает, включает процедуру ожидания квитанции реализованную в while true do ...Квитанция - от сервера опроса, реализованного на основе DDE технологии, то есть общая схема такая
Прога посылает запрос через ClientConv (все это в потоке) на считывание регистров DDE серверу и ждет квитанции от сервера. Сервер считав регистры посылает проге (клиенту) квитанцию о необходимости обновления данных с сервера (то есть на стороне сервера так же присутствует компонент DDE клиента а на стороне клиента для получения квитанции присутствует компонент DDE сервера). Серверный DDE компонент на стороне клиента получив команду (квитанцию) на обновление данных присваивает значение заданной переменной (kvit) значение true. Значение данной переменной в цикле потока while постоянно и проверяется( while not(kvit) do Application.ProcessMessegs ). После данного цикла идет запрос к серверу со стороны клиента на обновление данных - ClientConv.RequestData. И дальше sleep до следующего этапа опроса.
И вот я понимаю, что когда мы из программы и вызываем любое модальное окно во время цикла ожидания квитанции потока while , переменная квитанции почему-то не обновляется, хотя квитанция приходит и компонент DDEсервера на стороне клиент присвоение переменной производит, то есть отрабатывает и мы виснем... Передачу команд и квитанции реализовал через макросы...
И вот еще...
Без квитирования можно было бы обойтись если поставить в процедуре ClientConv.ExecuteMacroLines(...,fa lse) вместо false поставить true. То есть включить ожидание завершения макросов на стороне сервера и проверять постоянно завершение процедурой ClientConv.WaitStat, но опять же проблема (может я что не так делаю), даже когда на стороне сервера процедура ServerConv.OnExecuteMacro свое отработала, ClientConv.WaitStat все равно равен true и дальнейший доступ к серверу невозможен... (( в общем засада какая-то
Если по моей схеме "клиент-сервер" я что-то непонятно объяснил, готов все пояснить в картинках
bratcho вне форума Ответить с цитированием
Старый 02.12.2011, 18:31   #7
3D Hunter
Сумрачная тень
Форумчанин
 
Аватар для 3D Hunter
 
Регистрация: 05.03.2009
Сообщений: 689
По умолчанию

Цитата:
Модальное окно вызывается НЕ ВНУТРИ ПОТОКА.
и
Цитата:
при вызове модального окна из любой формы поток свое выполнение приостанавливает
это неправда. Поток будет работать в любом случае, если только вы не вызываете ShowModal из этого потока, или этот ShowModal находится в процедуре обрабоки вашей ПЛК.
"ковыряю изнутри" (с)
3D Hunter вне форума Ответить с цитированием
Старый 05.12.2011, 09:56   #8
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
Поток опроса у меня никаких модальных окон не вызывает.
ну хорошо, допустим прямых вызовов нет, а опосредовано?
Цитата:
Значение данной переменной в цикле потока while постоянно и проверяется( while not(kvit) do Application.ProcessMessegs )
Где как не здесь будет идти обработка очереди сообщений, а стало быть и SHOWMODAL попадет сюда.
А вы в курсе того что ShowModal тоже работает в ЭТОМ цикле. И МОДИФИЦИРЕТ параметры управления ДАННЫМ циклом, так как считает нужным. Вот вам и
Цитата:
а во время ожидания (sleep - реализованного внутри потока), то все нормуль, поток свое выполнение не приостанавливает, и поток выполняется дальше и выполняет периодический опрос с заданной частотой, а если мы модальное окно вызовем во время процедуры опроса, то выполнение приостанавливается.
Суда по вашему описанию поток вам нужен только для того чтобы постоянно с заданным интервалом (sleep) пинать основной поток для выполнения каких-то действий.
Цитата:
while not(kvit) do
Application.ProcessMessegs
это выполнение функций основного потока внутри потока.
и пока все операции основного потока не будут выполнены дальше вы не продвинетесь.

P.S. для синхронизации потоков используются семафоры и функции работы с ними Например
Цитата:
The WaitForSingleObject function returns when one of the following occurs:

· The specified object is in the signaled state.
· The time-out interval elapses.
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 05.12.2011 в 10:58.
evg_m вне форума Ответить с цитированием
Старый 05.12.2011, 15:30   #9
bratcho
Пользователь
 
Регистрация: 14.10.2011
Сообщений: 20
По умолчанию

Ура!!!
В общем выявил я в чем проблема, результаты своих проб и ошибок выкладываю в примерах, надеюсь этот опыт поможет другим, если кто столкнется с такой проблемой или решит реализовывать какую либо задачу таким способом. Решение состоит в том что процедуру ожидания while необходимо реализовывать не в теле какой либо процедуры (пусть даже она является методом потока) (пример_1) а в теле самого потока (пример_2) - Execute. Для того чтобы меня правильно поняли сделал пару примеров. Код простой в принципе и без комментариев все понятно, но тем не менее прокомментирую.
Пояснения привожу ниже...

По поводу "это неправда" - пример_1. Полностью отражает тот механизм который был описан ранее. Попробуйте сами и убедитесь, выкладываю вместе с исходниками. Суть в следующем. Есть поток - TPotok, который мы запускаем нажатием кнопки "Запуск потока".
Порядок действий в потоке следующий:
1 - вывод в поле memo момента начала выполнения потока
2 - ожидание прихода квитанции (ожидание когда переменная ExecuteCmd станет равной true - УЗКИЙ МОМЕНТ МОЕЙ ПРОГИ)
3 - вывод момента завершения потока
4 - разрушение потока по завершению выполнения

Приход квитанции, а именно присвоение переменной ExecuteCmd:=true, симитировал двумя способами - посредством таймера - через пять секунд после запуска потока и из модальной формы посредством нажатия кнопки. Модальная форма вызывается нажатием кнопки "Модальное окно".
Ну так вот, если запустить поток и не позднее 5-ти секунд с момента запуска вывести модальное окно, то в первом примере вы завершения потока (подтверждение тому вывод в поле memo - "end_дата/время") не дождетесь, не смотря на то что таймер свою задачу выполнит - присвоит переменной ExecuteCmd:=true - о чем будет свидетельствовать вывод даты/времени в memo поле "Результат работы таймера". Так же как я и говорил ранее ExecuteCmd:=true можно выполнить из модальной формы, но результата (завершения выполнения потока) не последует. Хотя все сделано вроде правильно и вызов процедуры в теле потока так же производится через Synchronize.

пример_2 - такими недостатками не обладает, только потому что процедуру while занес непосредственно в тело потока а не косвенно через пусть даже процедуры потока.

Большое всем спасибо за дискуссию и внимание к моей проблеме, надеюсь этот опыт будет еще кому-то полезен!
Вложения
Тип файла: rar примеры.rar (349.6 Кб, 18 просмотров)
bratcho вне форума Ответить с цитированием
Старый 05.12.2011, 17:24   #10
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
Решение состоит в том что процедуру ожидания while необходимо реализовывать не в теле какой либо процедуры (пусть даже она является методом потока) (пример_1) а в теле самого потока (пример_2) - Execute.
точнее говоря правильно использовать пооцедуру synchnize
неверно
Код:
procedure TPotok.Execute;
begin
  Synchronize(WaitProc);
end;
все выполнение в основном потоке (читаем для чего нужна Synchronize)

более правильно
основная работа потока ВНЕ процедуры synchonize.
Код:
procedure TPotok.Execute;
begin
  Synchronize(Wait_1);
// цикл выполнения ВНЕ Synchronize
  while not(ExecuteCmd) do
  begin
  end;
//
  Synchronize(Wait_2);
end;
хотя эта работа и бесполезна (в данном примере) т.к. вся ее задача дождаться какого-то действия (ExecuteCmd:=true) в основном потоке. Но думаю в рабочем варианте немного не так. Хотя... может там опять Synchonize. И если поток нужен только для того чтобы ОДИН раз дождаться чего-то от основного, то лучше бы его не было.
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Закрыть все дочерние (модальные и.д.) окна программы designer999 Общие вопросы Delphi 15 24.09.2011 18:49
Таймеры tools Qt и кроссплатформенное программирование С/С++ 3 30.05.2010 23:12
Таймеры Sergeu Общие вопросы C/C++ 2 25.03.2010 12:13
Таймеры EdNovice Общие вопросы .NET 1 06.03.2009 11:26
Модальные окна spamer Общие вопросы Delphi 4 01.03.2009 15:16