Как организовать досрочный выход из цикла?
| Правила | Регистрация | Пользователи | Сообщения за день |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Как организовать досрочный выход из цикла?

Как организовать досрочный выход из цикла?

Ответ
Поиск в этой теме
Непрочитано 18.01.2010, 23:12 #1
Как организовать досрочный выход из цикла?
[N.S]
 
инженер-дефектоскопист
 
Санкт-Петербург
Регистрация: 08.12.2006
Сообщений: 58

Как организовать досрочный выход из цикла по нажатию клавиши пользователем? Пробовал сделать через (grread T), но оказалось неприемлемо: вычисления останавливаются, ожидается действие пользователя.
Например, таким кодом можно накручивать мышкой или нажатием клавиш счетчик:
Код:
[Выделить все]
(setq do T i 0)
(while do
  ;;что-то делается
  (grtext (strcat "ЕДЕМ: " (itoa i)))
  (if (grread T) ;; ПРОВЕРКА?
      (setq do nil)
    )
  )
Чтобы счетчик мотал - нужно крутить педали..
А как можно сделать так, чтобы вычисления не останавливались в ожидании действий пользователя?
Просмотров: 11735
 
Непрочитано 18.01.2010, 23:38
#2
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,406


Нажатие Esc по идее как раз прерывает выполнение функции. Я на сайте у себя разбирал кое-что по этому поводу.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 18.01.2010, 23:50
#3
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


в функции grread есть возможность отслеживать не только перемещения курсора, но и нажатия клавиш на клавиатуре...
Достаточно сделать проверку возвращаемого кода из функции.
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Автор темы   Непрочитано 19.01.2010, 11:14
#4
[N.S]

инженер-дефектоскопист
 
Регистрация: 08.12.2006
Санкт-Петербург
Сообщений: 58


Елпанов Евгений: Да, но пока клавиша на клавиатуре не будет нажата, программа выполняться не будет. А нужно, чтоб вычисления не прерывались.. Код в первом посте наглядно иллюстрирует, что лисп останавливает выполнение в ожидании любого ввода пользователя (ввода с клавиатуры, преремещение курсора мышой и тп).
Кулик Алексей aka kpblc меня правильно понял: задача сделать экстренный выход из вычислений по нажатию клавиши. Esc прерывает выполнение команды автокада, но не прерывает выполнение лисп вычислений. Esc срабатывает если в коде есть grread. Но grread в ожидании ввода пользователя останавливает вычисления..(
[N.S] вне форума  
 
Непрочитано 19.01.2010, 11:32
#5
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,406


[N.S], так ты полностью задачку опиши. Возможно, все можно будет сделать совсем по-другому, привлекая пользователя только для экстренного прерывания выполнения. Опять же, намекаю на vl-catch-* функции
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 19.01.2010, 11:47
#6
VVA

Инженер LISP
 
Регистрация: 11.05.2005
Минск
Сообщений: 6,996


Попробуй использовать acet-sys-keystate из ExpressTools
acetutil.chm
Описание на afralisp
__________________
Как использовать код на Лиспе читаем здесь

Последний раз редактировалось VVA, 20.01.2011 в 14:36. Причина: Актуальная ссылка на afralisp
VVA вне форума  
 
Автор темы   Непрочитано 19.01.2010, 12:06
#7
[N.S]

инженер-дефектоскопист
 
Регистрация: 08.12.2006
Санкт-Петербург
Сообщений: 58


Цитата:
привлекая пользователя только для экстренного прерывания выполнения
- именно так и нужно.
Задача про проверку целостности трассы трубопровода.
Трубопровод состоит из 2М полилиний, которые либо имеют смежные точки, либо пересекаются, либо никак не связаны. Берется первая полилиния и от нее по цепочке строится трасса. Полилиний тысячи, вычисления до нескольких минут. А пользователь может понять, что ошибся в выборе начального элемента трассы и захочет вычисления прервать. Код написан, код длинный, код на работе - привести его здесь не могу. Думаю как организовать экстренное прерывание..
Кулик Алексей aka kpblc про vl-catch-* что ты имел ввиду? И вообще: какие есть пути решения?
VVA: А исходник acet-sys-keystate где найти можно? Как я понял эта функция использует GetKeyState() Windows User Interface, и до нее наверное можно через (vlax-get-or-create-object .. ) добраться?

Последний раз редактировалось [N.S], 19.01.2010 в 12:26. Причина: добавление
[N.S] вне форума  
 
Непрочитано 19.01.2010, 15:49
#8
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,406


Цитата:
Сообщение от [N.S
;507095]про vl-catch-* что ты имел ввиду? И вообще: какие есть пути решения?
Посмотри в библиотеке готовых функций _dwgru-error-catch. По-моему, она тебе в самый раз будет
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 19.01.2010, 20:47
#9
Pastor

это только кличка
 
Регистрация: 22.10.2006
Москва
Сообщений: 252


Создаю функцию, выполняющуюся "вечно":
Код:
[Выделить все]
Command: (defun assa () (while T))
ASSA
Вызываю её, и когда надоест, нажимаю Esc:
Код:
[Выделить все]
Command: (assa)
; error: Function cancelled
Функция принудительно завершается. Зачем надо что то городить с grread или с GetKeyState я не понял.
__________________
...в шее моей жилы железные, и лоб мой - медный...
Pastor вне форума  
 
Автор темы   Непрочитано 19.01.2010, 21:48
#10
[N.S]

инженер-дефектоскопист
 
Регистрация: 08.12.2006
Санкт-Петербург
Сообщений: 58


Pastor
Цитата:
нажимаю Esc:
- а ведь работает.. дома.. на 2006-м англ Автокаде. =))
[N.S] вне форума  
 
Непрочитано 19.01.2010, 23:21
#11
Pastor

это только кличка
 
Регистрация: 22.10.2006
Москва
Сообщений: 252


Снова не понял.
__________________
...в шее моей жилы железные, и лоб мой - медный...
Pastor вне форума  
 
Автор темы   Непрочитано 20.01.2010, 12:48
#12
[N.S]

инженер-дефектоскопист
 
Регистрация: 08.12.2006
Санкт-Петербург
Сообщений: 58


Разобрался.
Pastor, если выполняемая lisp функция задана в другом пространстве имен, то прервать ее по Esc невозможно. Откомпилировав вот это в VLX приложение (выбрав New Application Wizard - Expert - ... - Separate Namespace - ...)
Код:
[Выделить все]
(defun assa () (while T))
(vl-doc-export 'assa)
и вызвав
Код:
[Выделить все]
Command: (assa)
повесишь автокад.
Корректный экстренный выход нужно предусмотреть самому. Вопрос КАК?
[N.S] вне форума  
 
Непрочитано 20.01.2010, 14:01
#13
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,406


А если пространства имен не разделять? По идее код, аналогичный
Код:
[Выделить все]
(vl-load-com)

;;; http://forum.dwg.ru/showthread.php?t=22945

;;; ************************************************************************
;;; * Библиотека DWGruLispLib Copyright ©2007  DWGru Programmers Group
;;; *
;;; * Ловушка ошибок
;;; *
;;; * 13/11/2007 Версия 0001. Сергей Зуев   (ShaggyDoc)
;;; ************************************************************************
(defun dwgru-error-catch (protected_expression
                          on_error_expression
                          /
                          catch_error_result
                          )
;;;Назначение:

;;; Защита участка кода (выражения) от  потенциальной сбойной ситуации с
;;; предотвращением нештатного прерывания программы  и возможностью обработки
;;; сбойной ситуации.
  ;|
Аналог конструкции  try ...  except ... end; в Delphi.
Вызов:
(dwgru-error-catch   protected_expression on_error_expression)

Аргументы:
protected_expression - выражение, которое надо защитить от возможных сбойных
			ситуаций
on_error_expression - выражение, выполняющееся при возникновении ошибки, или
			nil, если ничего не требуется делать.

Возвращаемое значение:
  Результат выполнения protected_expression - при отсутствии ошибок или
результат выполнения on_error_expression - при возникновении ошибки.

Особенности:
  Разумное использование может полностью предотвратить возникновение ситуаций,
приводящих к вызову функции *error*.
  Не рекомендуется использование вложенных функций dwgru-error-catch.

Пример:
Организация ввода точки без возможности прерывания клавишей ESC.
(defun test001 (/ result)
 (while (not
  (dwgru-error-catch
   (function
    (lambda ()
     (setq result (getpoint "\nТочка (прерывание блокировано):"))
    ) ;_ end of lambda
   ) ;_ end of function
   (function
    (lambda (msg)
     (princ (strcat "\nТЕСТ прерывания - " msg))
     nil
    ) ;_ end of lambda
   ) ;_ end of function
  ) ;_ end of ru-error-catch
 ) ;_ end of while
 ) 
 result
)

|;
  (setq catch_error_result
         (vl-catch-all-apply protected_expression)
        ) ;_ end of setq
  (if (and (vl-catch-all-error-p catch_error_result)
           on_error_expression
           ) ;_ end of and
    (apply on_error_expression
           (list (vl-catch-all-error-message catch_error_result))
           ) ;_ end of apply
    catch_error_result
    ) ;_ end of if
  ) ;_ end of defun

(defun c:cmd_test ()
  (dwgru-error-catch
    (function
      (lambda ()
        (while t
         ) ;_ end of while
        ) ;_ end of lambda
      ) ;_ end of function
    (function
      (lambda (x)
        (princ (strcat "\n** error : " (vl-princ-to-string x)))
        ) ;_ end of lambda
      ) ;_ end of function
    ) ;_ end of dwgru-error-catch
  ) ;_ end of defun
должен работать корректно. Или нет?
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 20.01.2010, 18:49
#14
[N.S]

инженер-дефектоскопист
 
Регистрация: 08.12.2006
Санкт-Петербург
Сообщений: 58


Кулик Алексей aka kpblc Спасибо, протестировал предложенный код:
1) Если не компилировать:
Цитата:
Command: cmd_test
; entering keyboard break loop
2) Если скомпилировать VLX без разделения пространства имен:
Цитата:
Command: cmd_test
; entering keyboard break loop
3) Если скомпилировать VLX c разделением пространства имен: автокад висит.
Из 1) и 2) получается, что vl-catch-all-apply не ловит прерывание цикла по Esc. (Тогда бы перед ; entering keyboard break loop должно было вывестись ** error : )
3) Прервать цикл функции в другом пространстве имен по Esc по прежнему невозможно.
Вывод: не исползовать разделенное пространство имен (не хотелось бы), или использовать acet-sys-keystate из ExpressTools, как предложил VVA, или самому поднимать COM сервер чтоб задействовать GetKeyState() , как предлагают здесь http://forum.dwg.ru/showthread.php?t=46137
Есть еще варианты прервать лисп функцию из разделенного пространства имен?
[N.S] вне форума  
 
Непрочитано 20.01.2010, 23:17
#15
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


Цитата:
Сообщение от [N.S
;507032]Елпанов Евгений: Да, но пока клавиша на клавиатуре не будет нажата, программа выполняться не будет. А нужно, чтоб вычисления не прерывались.. Код в первом посте наглядно иллюстрирует, что лисп останавливает выполнение в ожидании любого ввода пользователя (ввода с клавиатуры, преремещение курсора мышой и тп).
немного не так, в действительности, каждый цикл проверки grread отнимает значительное время, если не трогать мышку или клаву, но это время является временем ожидания ввода...
Вот пример ожидающий нажатия любой клавиши на клавиатуре:
Код:
[Выделить все]
(defun c:test () (while (/= (car (grread nil 5 0)) 2)))
Пример можно усложнить ожиданием определенной клавиши, в данном случае "a" в английской раскладке:
Код:
[Выделить все]
(defun c:test () (while (not (equal (grread nil 8 0) '(2 97)))))
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Автор темы   Непрочитано 21.01.2010, 10:40
#16
[N.S]

инженер-дефектоскопист
 
Регистрация: 08.12.2006
Санкт-Петербург
Сообщений: 58


Елпанов Евгений:
Цитата:
цикл проверки grread отнимает значительное время, если не трогать мышку или клаву, но это время является временем ожидания ввода...
Вот это самое ожидание ввода не дает остальной программе выполняться..
[N.S] вне форума  
 
Непрочитано 21.01.2010, 10:45
#17
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


Цитата:
Сообщение от [N.S
;508407]Вот это самое ожидание ввода не дает остальной программе выполняться..
Как это не дает?
Если нет никаких движений, то каждый цикл проверки отнимает чуть меньше половины секунды...
Код:
[Выделить все]
(defun c:test ()(setq i 1) (while (not (equal (grread t 7 0) '(2 97)))(setq i (1+ i)))(princ i)(princ))
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Автор темы   Непрочитано 21.01.2010, 12:19
#18
[N.S]

инженер-дефектоскопист
 
Регистрация: 08.12.2006
Санкт-Петербург
Сообщений: 58


Елпанов Евгений
Цитата:
каждый цикл проверки отнимает чуть меньше половины секунды...
- не согласен. Я запустил предложенный код и получил i=2, (нажал один раз Ecs).
Вот измененный вариант кода верхнего поста, который выводит текущее значение счетчика в строку состояния (вроде так называется, то куда (grtext -1 ..) шлет). Запустив, его можно наблюдать, как каждое нажатие или движение мыши увеличивает счетчик на единицу (мгновенно). При этом если ничего не жать и не двигать, счетчик не изменяется. следовательно, лисп не выполняется, а ждет ввода пользователя. Если шевелить мышью, то видно что счетчик изменяется оч. быстро, значит цикл проверки занимает много меньше пол секунды.
Код:
[Выделить все]
(defun c:test ()
  (setq i 0)
  (while (not (equal (grread t 7 0) '(2 97)))
    ;; Вывод счетчика в строку состояния
    (grtext -1 (itoa i))
    (setq i (1+ i))
    )
  )
[N.S] вне форума  
 
Непрочитано 21.01.2010, 12:52
#19
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


Цитата:
Сообщение от [N.S
;508511] При этом если ничего не жать и не двигать, счетчик не изменяется. следовательно, лисп не выполняется, а ждет ввода пользователя.
Допускаю, что в твоей версии автокада, действительно нет изменений...
Посмотри видео, как это выглядит у меня. Сверху, я специально поставил часики, чтоб можно было видеть текущее время и сравнить скорость обновления...
Вложения
Тип файла: flv aaa.flv (144.6 Кб, 118 просмотров)
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Автор темы   Непрочитано 21.01.2010, 13:05
#20
[N.S]

инженер-дефектоскопист
 
Регистрация: 08.12.2006
Санкт-Петербург
Сообщений: 58


Елпанов Евгений Верю) У меня 2006 и 2008 англиские версии автокада - и счетчик не меняется. Впрочем, не может ли быть что какое-то устройство таки у тебя дает регулярный сигнал? И все же скорость опроса (grread) на порядки выше пол секунды..
[N.S] вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Как организовать досрочный выход из цикла?



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Сейсмозащита и сейсмоизоляция существующих, построенных зд. IANationalInformAgentstvo Прочее. Архитектура и строительство 216 20.01.2015 16:51
Как именно настроить параметры нового чертежа? Макс_Северянин AutoCAD 31 01.09.2010 10:16
Как организовать событие "Закончилась минута"? kos Программирование 21 16.03.2009 12:31
Мониторы LCD CRT Разное 94 17.06.2008 10:51
Как организовать линейный шарнир в Скаде SkiFF SCAD 4 26.03.2006 14:50