| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Для новичков > Исключение вылезает за try-except |
| Автор: kami 14.10.2013, 08:59 | ||||
| Доброго времени суток, уважаемые: от слов к коду. есть поток:
В обработчике таймера:
Периодически (пользуюсь MadExcept) "наружу" вылезает исключение EArgumentOutOfRangeException, т.е. на экране появляется окошко MadExcept-ов с кнопочками "продолжить, перезапустить..." Вопрос: почему оно, это окошко, вылезает? Ведь обработка WM_TIMER обернута в try-except, соответственно - исключение должно записаться в лог и уйти на следующий виток while. Чего я не понимаю и что делаю не так? |
| Автор: kami 14.10.2013, 12:38 | ||
Вылезает не всегда (имеется ввиду - не на каждом вызове события таймера), но при работе из-под IDE, как ни старался, отловить не удалось. P.S. Используется стандартный TTimer. Причину возникновения EArgumentOutOfRangeException я уже отловил и устранил, но - с чего оно вылезло за except-блок? UPD. Нашел, в чем дело. Исходный код оконной процедуры Ttimer:
|
| Автор: Akella 14.10.2013, 14:32 |
По твоему коду непонятно, где именно. Если окно с сообщением об исключении вываливается при работе аппликации из-под IDE (отладчика), то это нормально. |
| Автор: kami 14.10.2013, 14:47 | ||
Если вываливается сообщение самого IDE (там, где есть чекбокс "игнорировать в будущем") - да, это нормально. Но оно останавливает работу потока в "боевом" режиме, не из-под IDE. Я привел не полный код? Вроде, весь, относящийся к делу (пост №1): в потоке создана очередь сообщений, которые вылавливаются в цикле. Каждая итерация цикла заключена в try-except. Приходит сообщение WM_TIMER, оно через DispatchMessage и оконную процедуру таймера попадает в обработчик OnTimer, там возбуждается исключение, но оно не "гасится" в except-блоке цикла обработки сообщений, хотя - должно. В принципе, причина выяснена - оконная процедура TTimer самостоятельно вызывает Application.HandleException (кто б ее об этом еще просил). Осталось выяснить - как с этим бороться. Единственное, что приходит в голову - каждый обработчик OnTimer нужно заключать в try-except, что мне совсем не улыбается. |
| Автор: kami 14.10.2013, 20:16 | ||
Кстати, в этом случае получается, что я не могу передать возбужденное в OnTimer исключение "вверх" на уровень... Плохо... Upd. Либо - хватать Application.OnException и там... - re-raise что ли, но это вообще не нескафе... |
| Автор: Alexeis 17.10.2013, 09:18 |
| Делфя старается перехватывать все исключения в главном потоке. TTimer это компонент. Как известно, в делфях предполагается, что компоненты работают в главном потоке. В данном случае проще свой класс таймера написать. Тем более что там 3.5 строчки кода. Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Исключение-вылезает-за-try-except-id525b8862ae2015960f000000#findElement_E7045_525f8132ae2015754700026d_0 |
| Автор: Akella 17.10.2013, 09:51 |
| Создай поток с событием, в котором будет срабатывать процедура через определённые интервалы времени. Если что, у меня есть готовый пример. |
| Автор: kami 21.10.2013, 11:43 | ||
Это понятно. Однако, исключение и так будет перехвачено в Application.Run, в цикле обработки сообщений (да, в предыдущих сообщениях неправильно написал - ProcessMessages, по крайней мере в D2010, не ограждено try-except). На кой нужен прямой вызов HandleException из оконной процедуры таймера - так и не понял. В общем и целом - вопрос решен: Было бы неплохо, т.к. не понимаю, как это - |
| Автор: Akella 22.10.2013, 09:28 | ||||||
где-нибудь в приложении, например, в главной форме
если нужно вызвать thread.execute принудительно, не дожидаясь, пока таймер сработает, можно вызвать в любой момент:
|
| Автор: Akella 22.10.2013, 09:49 |
| https://www.google.com/search?q=thread+WaitForSingleObject&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ru:official&client=firefox-a&channel=fflb#channel=fflb&lr=lang_ru&q=delphi+thread+WaitForSingleObject&rls=org.mozilla:ru%3Aofficial&tbs=lr:lang_1ru |
| Автор: kami 22.10.2013, 09:50 |
Понятно. Мне больше бы подошло RegisterWaitForSingleObject, с которым так и недопереразобрался. Тормозить очередь сообщений на WaitFor - не комильфо. Спасибо. |
| Автор: Akella 22.10.2013, 14:22 |
не понял Добавлено через 23 секунды А я думал, что это самый правильный подход. Добавлено через 1 минуту и 13 секунд вот ещё посмотри http://www.sql.ru/forum/1050286/shablon-klassa-dlya-raboty-s-potokom-wthread-thread |
| Автор: kami 22.10.2013, 14:40 |
Если (как, допустим, в примере) ставить в WaitFor dwMilliseconds = 1000, то получается, что ни одно окно (из числа созданных в этом потоке) целую секунду не сможет получить ни одного сообщения. |
| Автор: bems 22.10.2013, 15:36 |
| так тебе говорят про отдельный поток, в котором нет гуя |
| Автор: kami 22.10.2013, 15:51 | ||
При чем здесь гуй? У меня в сабжевом потоке крутятся: - окно таймера - окно, к которому привязан IWebBrowser (да и сам IWB кучу всего похоже создает) - окно обслуживания синхронизации данных между потоками (что-то типа коллбаков хуков в Винде). И ничего из этого не является GUI. Но всем этим окнам нужно обрабатывать сообщения (особенно - второму и третьему). Добавлено через 1 минуту и 50 секунд
Только сейчас дошло: спасибо было сказано безо всякого подтекста - действительно за напоминание такой возможности. |
| Автор: bems 22.10.2013, 15:58 | ||
| ну понятно, но речь идет об отдельном потоке-таймере. если не хочешь - RegisterWaitForSingleObject в чем проблема я не пойму?
|
| Автор: kami 22.10.2013, 16:08 | ||
Изначально речь шла о не-джентльменском поведении стандартного TTimer в потоке А потом уже Akella привел код потока-таймера. Я же (наверное, некорректно) написал, что такой подход не совсем вписывается в задачу моего потока. Да проблемы-то уже и нет, она решена
Просто было интересен код, который предложил Akella Вот беседа немножко и подзатянулась. |
| Автор: Akella 22.10.2013, 22:11 | ||
Обычно в потоке выполняют работу безо всяких окон. Это отдельный поток. У меня в отдельном потоке таким образом выполняется процедура экспорта в XML и отправка данных на хостинг. В другом приложении программа в отдельном потоке раз в минуту выполняет (образно говоря) idHttp.Get(...), при этом, пользователь спокойно работает с программой, даже не замечая, что выполняется что-то в отдельном потоке раз в минуту. или я тебя не понял? |
| Автор: kami 23.10.2013, 12:42 |
Да вроде всё правильно. Тем не более, я не согласен с утверждением У меня редко когда получается без них обойтись. Под "окнами в потоках" я понимаю всё созданное через AllocateHWND и/или CreateWindow[Ex]... |
| Автор: bems 23.10.2013, 14:23 |
у меня чаще получается чем не получается, но у тебя же webbrowser control живёт в этом треде, а com-объекты требуют обработки сообщений в своём apartment-треде, тут ничего не сделаешь. смотри в сторону CoWaitForMultipleHandles или обрабатывай WM_TIMER руками |