Страница: 1 |
Страница: 1 |
Вопрос: Остановка/продолжение программы пользователем
Добавлено: 14.08.12 21:03
Автор вопроса: merr
Добрых суток времени всем :)
Народ, кто-нибудь знает можно ли сделать так, чтоб юзер мог легким нажатием кнопки остановить выполнение процедуры, но без выхода из нее, а также нажатием (другой) кнопки продолжить выполнение именно с этого же места. Процедура представляет собой цикл с задержкой - чтоб юзер успел увидеть изменение параметров на экране.
Может есть функции такие специальные?
Ответы
Всего ответов: 13
Номер ответа: 1
Автор ответа:
Millenium
ICQ: 629966
Вопросов: 118
Ответов: 903
Web-сайт:
Профиль | | #1
Добавлено: 14.08.12 21:28
может.
Создай переменную
а после перехватывай нажатие совей кнопки А для "паузы" и Б для "возобновления".
и при нажатии кнопки А İsPaused = True и обратно - Б İsPaused = False.
и в модуле проверяй,
if IsPaused = True Then
Номер ответа: 2
Автор ответа:
Avvelana
Вопросов: 2
Ответов: 18
Профиль | | #2
Добавлено: 14.08.12 21:29
Хм. Функции есть, но боюсь их реализация не стоит полученного результата. Вообще нужно использовать функции отладки. Думаю как-то так: Cоздаём новый поток, отправляем обработку текущей функции туда (SetThreadContext или что-то подобное). При этом предусматриваем механизм, чтобы функция продолжала работать в новом потоке. Далее делаем DebugBreak() или Sleep() на поток. Отрабатываем в новом потоке то, что нужно, далее передаём управление первому потоку, убиваем второй (что довольно сложно сделать правильно, очистка памяти и тд.) и продолжаем первый (ContinueDebugEvent или что-то подобное). В общем это будет кошмар, я бы не связывался с такими штуками. Возможно есть другие методы, но мне на ум ничего больше не приходит.
Номер ответа: 3
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #3
Добавлено: 14.08.12 22:12
К сожалению автор не указал язык реализации, но если речь идет о .НЕТ, то там для этих целей есть куча возможностей. Это,собственно, все наследники WaitHandle (к примеру ManualResetEvent).Кроме того есть еще всякие Mutex, Semaphore и прочие прибамбасы которые тоже вполне подойдут для этих целей.. Да даже обычную критическую секцию в виде Monitor.Enter/Lock можно приспособить чтоб заморозить тред
Номер ответа: 4
Автор ответа:
merr
Вопросов: 11
Ответов: 31
Профиль | | #4
Добавлено: 14.08.12 22:54
Да, извините что не указал - на VB6 все это безобразие нужно проделать...
Номер ответа: 5
Автор ответа:
Artyom
Разработчик
Вопросов: 130
Ответов: 6602
Профиль | | #5
Добавлено: 15.08.12 00:34
и в модуле проверяй,
if IsPaused = True Then
"Приостановка процедуры" фактически означает приостановку потока, выполняющего эту процедуру. Windows поддерживает возможность остановки потока. Если не ошибаюсь, это делается фукнцией SuspendThread. После этого поток переходит в спящее состоянии до того момента как его не "разбудят". По понятным (надеюсь) причинам разбудить поток можно только из другого потока, который еще выполняется.
Это в теории.
На практике - есть ряд особенностей.
Например, в VB6 вся программа выполняется в единственном потоке, который выполняет цикл обработки сообщений Windows. Приостановка этого потока будет означать полное зависание программы (перестанет отрисовываться UI и отвечать на действия пользователя), и возобновить выполнение программы уже будет невозможно.
В твоем случае запускать выполнение нужно в другом потоке (не UI потоке) и его же останавливать из UI потока.
Кроме того, асинхронная остановка потока (когда поток останавливается по команде извне, а не по собственной инициативе) - очень опасная практика которую нужно использовать с осторожностью (вернее вообще не использовать). Восновном проблемы связаны с тем, что не известно, что именно будет выполнять поток в момент своей остановки. А он может заниматься выделением памяти, созданием объектов ядра, выполнением транзакции и т.п. За подробностями гуглите "Why you should not suspend thread"
Если требуется возможность приостанавливать выполнение процедуры, такая возможность должна быть предусмотрена в самой процедуре. Например, в цикле периодически проверяется какой-то флаг, и если он установлен (а это может быть сделано из другого потока), то поток самостоятельно переводит себя в спящее состояние (способов хватает, обычно это делают объектами синхронизации режима ядра).
Это в теоритической практике.
А в практической практике на VB6 об этом фактически можно забыть. Запуск нового потока в VB6 займет примерно столько же времени сколько изучения C# на уровне, достаточном для того чтоб писать программы, котоыре ты пишешь сейчас.
Так вот, дорогой анон, если тебе удалось запустить поток (что делается несколько сложнее чем в самом С++), и ничего не упало, это не значит что твои приключения закончились. Поскольку после запуска потоков тебе потребуется делать синхроинзацию (что сравнимо по сложности с тем как это делается в С++), а также делать отладку программы (что уже практически невозможно). В любом случае про отшумевший Rapid Application Development и программирование мышкой можно будет забыть, для любого чиха нужно будет юзать голые функции Win32API (если, конечно, кто-то уже не умудрился запилить библиотеку классов для многопоточности под VB6, вот только кто, как и на***?)
=============================================
ну а вообще возникюет вопрос
Например, как у тебя сейчас вообще во время выполнения длительной процедуры "нажимается" кнопка если весь UI должен по идее висеть.
=========================
Реализация того что ты хотел без многопоточности возможна. При этом нужно будет смириться с тем, что производительность просядет (не знаю насколько, возможно, даже в разы), несмотря на то что нагрузка на процессор останется без изменнеий
Для этого нужно:
1) В каждой итерации цикла вызывать Application.DoEvents()
2) Реализовать механизм, котоыре позволяет сохранить состояние, в котором находится процедура и прервать ее выполнение, чтоб при следующем вызове она могла продолжить выполнение точно на том месте, на котором остановилась.
3) Либо же во время "приостановки" просто заходить в пустой цикл с одним лишь Application.DoEvents(), но будь готов к полной загрузке процессора (впрочем, владельцы 8-ядерных Core i7 вряд ли заметят подставу).
Вобщем найти хоть какое-нибудь разумное обоснование заниматься этой ***й (вместо того чтоб взять наконец и выучить С++, C# или Java) я лично не могу.
Номер ответа: 6
Автор ответа:
merr
Вопросов: 11
Ответов: 31
Профиль | | #6
Добавлено: 15.08.12 01:35
Artyom, спасибо столь подробный ответ!
У меня далеко не i7, с DoEvents в цикле приложение мертво висит.
Абсолютно согласен, нужно переходить на C#... После полугода VB6 это много легче, чем с нуля
Номер ответа: 7
Автор ответа:
LamerOnLine
ICQ: 334781088
Вопросов: 108
Ответов: 2822
Профиль | | #7
Добавлено: 15.08.12 10:17
Вопрос не языка а реализации. Юзать SuspendThread - дурное правило. Процедура должна сама предусматривать возможные точки останова. Как ты их реализуешь - через евенты, таймеры или как то еще - дело хозяйское.
А использовать DoEvent в каждой минимальной итерации - не просто изврат. Это Ахтунг!
Номер ответа: 8
Автор ответа:
EROS
Вопросов: 58
Ответов: 4255
Профиль | | #8
Добавлено: 15.08.12 11:07
Юзать SuspendThread - дурное правило
Так никто и не говорил про Suspend. Более того в НЕТ он является depricated. А предложенный мною WaitHandle являются стандартным механизмом синхронизации и проверен уже не одну сотню раз.
Процедура должна сама предусматривать возможные точки останова.
Именно это и предусматривает использование WaitHandle
Номер ответа: 9
Автор ответа:
LamerOnLine
ICQ: 334781088
Вопросов: 108
Ответов: 2822
Профиль | | #9
Добавлено: 16.08.12 14:13
Про SuspendThread упомянул Artyom. Что в этом такого если у человека такой стиль программирования - использовать в основном deprecated функции и помечать результирующий код как deprecated. Такой вот своеобразый стайл
Номер ответа: 10
Автор ответа:
Nash Bridges
Вопросов: 5
Ответов: 139
Профиль | | #10
Добавлено: 18.08.12 04:57
Ему в первом посте сказали как делать.
Умничать не надо, а то горе от ума будет.
Номер ответа: 11
Автор ответа:
Nash Bridges
Вопросов: 5
Ответов: 139
Профиль | | #11
Добавлено: 18.08.12 04:57
Ему в первом посте сказали как делать.
Умничать не надо, а то горе от ума будет.
Номер ответа: 12
Автор ответа:
BG(Алексей)
Вопросов: 26
Ответов: 295
Профиль | | #12
Добавлено: 23.08.12 06:03
1) В каждой итерации цикла вызывать Application.DoEvents()
Номер ответа: 13
Автор ответа:
BG(Алексей)
Вопросов: 26
Ответов: 295
Профиль | | #13
Добавлено: 23.08.12 06:07
Нужно, всего лишь, забыть про усопший VB6 и загрузить VB.Net