Модераторы: Snowy, MetalFan, bems, Poseidon

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Исключение вылезает за try-except, Почему? 
V
    Опции темы
kami
Дата 14.10.2013, 08:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Доброго времени суток, уважаемые:
от слов к коду.
есть поток:
Код

procedure TMySuperThread.Execute;
var
  MSG: TMsg;
begin
  PeekMessage(MSG, 0, WM_USER, WM_USER, PM_NOREMOVE);
  CreateComponents; // тут создается таймер
  try
    while not Terminated and GetMessage(MSG, 0, 0, 0) do
      try
        if MSG.hwnd <> 0 then
          begin
            TranslateMessage(MSG);
            DispatchMessage(MSG);
          end;
      except
        on e: Exception do
          LogFileX.LogException(e);
      end;
  finally
    DestroyComponents;
  end;
end;


В обработчике таймера:
Код

    for i := FWSList.Count - 1 downto 0 do // FWSList = TObjectList<TWS>
        begin
          WS:=FWSList[i]; // вот тут - исключение EArgumentOutOfRangeException
          ...// тут производятся какие-то действия, в том числе, возможно, удаление объекта WS.


Периодически (пользуюсь MadExcept) "наружу" вылезает исключение EArgumentOutOfRangeException, т.е. на экране появляется окошко MadExcept-ов с кнопочками "продолжить, перезапустить..."

Вопрос:
почему оно, это окошко, вылезает? Ведь обработка WM_TIMER обернута в try-except, соответственно - исключение должно записаться в лог и уйти на следующий виток while.
Чего я не понимаю и что делаю не так?
PM MAIL WWW   Вверх
Akella
Дата 14.10.2013, 12:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 8
Всего: 329



Цитата(kami @  14.10.2013,  08:59 Найти цитируемый пост)
почему оно, это окошко, вылезает? Ведь обработка WM_TIMER обернута в try-except, 

Вылезает всегда или только во время работы из-под IDE?
PM MAIL   Вверх
kami
Дата 14.10.2013, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(Akella @  14.10.2013,  12:28 Найти цитируемый пост)
Вылезает всегда или только во время работы из-под IDE?

Вылезает не всегда (имеется ввиду - не на каждом вызове события таймера), но при работе из-под IDE, как ни старался, отловить не удалось.
P.S. Используется стандартный TTimer.
Причину возникновения EArgumentOutOfRangeException я уже отловил и устранил, но - с чего оно вылезло за except-блок?

UPD. Нашел, в чем дело. Исходный код оконной процедуры Ttimer:
Код

with Msg do
    if Msg = WM_TIMER then
      try
        Timer;
      except
        Application.HandleException(Self); // вот оно. Ну и как с этим бороться??? С какого перепугу тут образовался Application?
// у него же есть свой try-except в ProcessMessages.
      end
    else
      Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);


Это сообщение отредактировал(а) kami - 14.10.2013, 12:40
PM MAIL WWW   Вверх
Akella
Дата 14.10.2013, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 8
Всего: 329



Цитата(kami @  14.10.2013,  12:38 Найти цитируемый пост)
но - с чего оно вылезло за except-блок?


По твоему коду непонятно, где именно.
Если окно с сообщением об исключении вываливается при работе аппликации из-под IDE (отладчика), то это нормально.

PM MAIL   Вверх
kami
Дата 14.10.2013, 14:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(Akella @  14.10.2013,  14:32 Найти цитируемый пост)
Если окно с сообщением об исключении вываливается при работе аппликации из-под IDE (отладчика), то это нормально.

Если вываливается сообщение самого IDE (там, где есть чекбокс "игнорировать в будущем") - да, это нормально. Но оно останавливает работу потока в "боевом" режиме, не из-под IDE.


Цитата(Akella @  14.10.2013,  14:32 Найти цитируемый пост)
По твоему коду непонятно, где именно.

Я привел не полный код? Вроде, весь, относящийся к делу (пост №1):
в потоке создана очередь сообщений, которые вылавливаются в цикле. Каждая итерация цикла заключена в try-except. 
Приходит сообщение WM_TIMER, оно через DispatchMessage и оконную процедуру таймера попадает в обработчик OnTimer, там возбуждается исключение, но оно не "гасится" в except-блоке цикла обработки сообщений, хотя - должно.

В принципе, причина выяснена - оконная процедура TTimer самостоятельно вызывает Application.HandleException (кто б ее об этом еще просил).
Осталось выяснить - как с этим бороться. Единственное, что приходит в голову - каждый обработчик OnTimer нужно заключать в try-except, что мне совсем не улыбается.
PM MAIL WWW   Вверх
kami
Дата 14.10.2013, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(kami @  14.10.2013,  14:47 Найти цитируемый пост)
каждый обработчик OnTimer нужно заключать в try-except, что мне совсем не улыбается.

Кстати, в этом случае получается, что я не могу передать возбужденное в OnTimer исключение "вверх" на уровень... Плохо...

Upd.
Либо - хватать Application.OnException и там... - re-raise что ли, но это вообще не нескафе...

Это сообщение отредактировал(а) kami - 14.10.2013, 20:26
PM MAIL WWW   Вверх
Alexeis
Дата 17.10.2013, 09:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 34
Всего: 459



  Делфя старается перехватывать все исключения в главном потоке. TTimer это компонент. Как известно, в делфях предполагается, что компоненты работают в главном потоке. В данном случае проще свой класс таймера написать. Тем более что там 3.5 строчки кода.

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM ICQ Skype   Вверх
Akella
Дата 17.10.2013, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 8
Всего: 329



Создай поток с событием, в котором будет срабатывать процедура через определённые интервалы времени.

Если что, у меня есть готовый пример.
PM MAIL   Вверх
kami
Дата 21.10.2013, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(Alexeis @  17.10.2013,  09:18 Найти цитируемый пост)
Делфя старается перехватывать все исключения в главном потоке. TTimer это компонент. Как известно, в делфях предполагается, что компоненты работают в главном потоке.

Это понятно. Однако, исключение и так будет перехвачено в Application.Run, в цикле обработки сообщений (да, в предыдущих сообщениях неправильно написал - ProcessMessages, по крайней мере в D2010, не ограждено try-except). На кой нужен прямой вызов HandleException из оконной процедуры таймера - так и не понял.
В общем и целом - вопрос решен:
Цитата(Alexeis @  17.10.2013,  09:18 Найти цитируемый пост)
 В данном случае проще свой класс таймера написать.



Цитата(Akella @  17.10.2013,  09:51 Найти цитируемый пост)
Если что, у меня есть готовый пример.

Было бы неплохо, т.к. не понимаю, как это - 
Цитата(Akella @  17.10.2013,  09:51 Найти цитируемый пост)
Создай поток с событием,


PM MAIL WWW   Вверх
Akella
Дата 22.10.2013, 09:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 8
Всего: 329



Код


type
  TMyThread = class(TThread)

  private
    FTerminateEvent: THandle;
   fInerval: integer;
...
...
  public
    property TerminateEventHandle: THandle read FTerminateEvent write FTerminateEvent;
    property Inerval: integer read fInerval write fInerval;
...
...

...
    procedure Execute; override;
  end;


implementation


procedure TMyThread.Execute;
begin

try
    FTerminateEvent := CreateEvent(Nil, False, False, Nil);
    SetEvent(FTerminateEvent);

    while not Terminated do
    begin
        if Terminated then Break;

        try
// fInerval - интервал срабатывания в миллисекундах, как у таймера, 1000 = 1 сек.

//выполняться начнёт только после того, как наступит время fInerval или будет вызвано где-нибудь SetEvent(Thread1.TerminateEventHandle);
          if WaitForSingleObject(FTerminateEvent, fInerval) <> WAIT_ABANDONED Then // вместо sleep
          begin
            if Terminated then exit;
             // выполняем в потоке нужную работу

          end;// if

        except
          on e:exception do
            raise;

        end;// try except

finlly
    if FTerminateEvent > 0 then
      CloseHandle(FTerminateEvent);

end;




где-нибудь в приложении, например,  в главной форме 

Код

Thread1: TMyThread;//объявляем
...
...

//по команде создаём запускаем
  Thread1 := TMyThread.Create(True);
  try
    Thread1.Priority := tpNormal;
    Thread1.FreeOnTerminate := true;
    Thread1.Inerval := VarToInt(spinInerval.EditValue, 0) * 1000 * 60;//время
  except
    if Assigned(Thread1) then
      FreeAndNil(Thread1);

    raise;
  end;

  Thread1.Start;// поток будет создан и запущен, но выполняться начнёт только после того, как наступит время


если нужно вызвать thread.execute принудительно, не дожидаясь, пока таймер сработает, можно вызвать в любой момент:
Код

SetEvent(Thread1.TerminateEventHandle);

PM MAIL   Вверх
Akella
Дата 22.10.2013, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 8
Всего: 329



PM MAIL   Вверх
kami
Дата 22.10.2013, 09:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(Akella @  22.10.2013,  09:28 Найти цитируемый пост)
if WaitForSingleObject(FTerminateEvent, fInerval)

Понятно. Мне больше бы подошло RegisterWaitForSingleObject, с которым так и недопереразобрался. Тормозить очередь сообщений на WaitFor - не комильфо.
Спасибо.
PM MAIL WWW   Вверх
Akella
Дата 22.10.2013, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 8
Всего: 329



Цитата(kami @  22.10.2013,  09:50 Найти цитируемый пост)
Тормозить очередь сообщений на WaitFor - не комильфо.

не понял

Добавлено через 23 секунды
А я думал, что это самый правильный подход.

Добавлено через 1 минуту и 13 секунд
вот ещё посмотри http://www.sql.ru/forum/1050286/shablon-kl...-wthread-thread
PM MAIL   Вверх
kami
Дата 22.10.2013, 14:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(Akella @  22.10.2013,  14:22 Найти цитируемый пост)
не понял

Если (как, допустим, в примере) ставить в WaitFor dwMilliseconds = 1000, то получается, что ни одно окно (из числа созданных в этом потоке) целую секунду не сможет получить ни одного сообщения.
PM MAIL WWW   Вверх
bems
Дата 22.10.2013, 15:36 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88



так тебе говорят про отдельный поток, в котором нет гуя


--------------------
Обижено школьников: 8
PM MAIL   Вверх
kami
Дата 22.10.2013, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(bems @  22.10.2013,  15:36 Найти цитируемый пост)
в котором нет гуя

При чем здесь гуй?
У меня в сабжевом потоке крутятся:
- окно таймера
- окно, к которому привязан IWebBrowser (да и сам IWB кучу всего похоже создает)
- окно обслуживания синхронизации данных между потоками (что-то типа коллбаков хуков в Винде).
И ничего из этого не является GUI. Но всем этим окнам нужно обрабатывать сообщения (особенно - второму и третьему).

Добавлено через 1 минуту и 50 секунд
Цитата(kami @  22.10.2013,  09:50 Найти цитируемый пост)
Понятно. Мне больше бы подошло RegisterWaitForSingleObject, с которым так и недопереразобрался. Тормозить очередь сообщений на WaitFor - не комильфо.
Спасибо.

Только сейчас дошло: спасибо было сказано безо всякого подтекста - действительно за напоминание такой возможности.
PM MAIL WWW   Вверх
bems
Дата 22.10.2013, 15:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88



ну понятно, но речь идет об отдельном потоке-таймере. если не хочешь - RegisterWaitForSingleObject
в чем проблема я не пойму?

Цитата(kami @  22.10.2013,  15:51 Найти цитируемый пост)
окно, к которому привязан IWebBrowser (да и сам IWB кучу всего похоже создает)
ну для ком-тредов есть CoWaitForMultipleHandles



--------------------
Обижено школьников: 8
PM MAIL   Вверх
kami
Дата 22.10.2013, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(bems @  22.10.2013,  15:58 Найти цитируемый пост)
но речь идет об отдельном потоке-таймере. 

Изначально речь шла о не-джентльменском поведении стандартного TTimer в потоке smile 
А потом уже Akella привел код потока-таймера. Я же (наверное, некорректно) написал, что такой подход не совсем вписывается в задачу моего потока.


Цитата(bems @  22.10.2013,  15:58 Найти цитируемый пост)
в чем проблема я не пойму?

Да проблемы-то уже и нет, она решена
Цитата(kami @  21.10.2013,  11:43 Найти цитируемый пост)
В общем и целом - вопрос решен:Цитата(Alexeis @  17.10.2013,  09:18 ) В данном случае проще свой класс таймера написать.


Просто было интересен код, который предложил Akella 
Цитата(Akella @  17.10.2013,  09:51 Найти цитируемый пост)
Если что, у меня есть готовый пример.

Вот беседа немножко и подзатянулась.
PM MAIL WWW   Вверх
Akella
Дата 22.10.2013, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 8
Всего: 329



Цитата(kami @ 22.10.2013,  14:40)
Цитата(Akella @  22.10.2013,  14:22 Найти цитируемый пост)
не понял

Если (как, допустим, в примере) ставить в WaitFor dwMilliseconds = 1000, то получается, что ни одно окно (из числа созданных в этом потоке) целую секунду не сможет получить ни одного сообщения.

Обычно в потоке выполняют работу безо всяких окон.
Это отдельный поток.
У меня в отдельном потоке таким образом выполняется процедура экспорта в XML и отправка данных на хостинг.
В другом приложении программа в отдельном потоке раз в минуту выполняет (образно говоря) idHttp.Get(...), при этом, пользователь спокойно работает с программой, даже не замечая, что выполняется что-то в отдельном потоке раз в минуту.

или я тебя не понял?
PM MAIL   Вверх
kami
Дата 23.10.2013, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(Akella @  22.10.2013,  22:11 Найти цитируемый пост)
или я тебя не понял?

Да вроде всё правильно.
Тем не более, я не согласен с утверждением 
Цитата(Akella @  22.10.2013,  22:11 Найти цитируемый пост)
Обычно в потоке выполняют работу безо всяких окон.
 У меня редко когда получается без них обойтись.
Под "окнами в потоках" я понимаю всё созданное через AllocateHWND и/или CreateWindow[Ex]...

PM MAIL WWW   Вверх
bems
Дата 23.10.2013, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88



Цитата(kami @  23.10.2013,  12:42 Найти цитируемый пост)
У меня редко когда получается без них обойтись.

у меня чаще получается чем не получается, но у тебя же webbrowser control живёт в этом треде, а com-объекты требуют обработки сообщений в своём apartment-треде, тут ничего не сделаешь. смотри в сторону CoWaitForMultipleHandles или обрабатывай WM_TIMER руками


--------------------
Обижено школьников: 8
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1091 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.