Модераторы: 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   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

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

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

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

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


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

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


 




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


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

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