| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Вызов функции по таймеру |
| Автор: Lexicss 26.5.2007, 00:40 | ||
| Привет, народ! Давно уже не заходил на форум. Вот тут упёрся в одну проблемку, может вы поможете разобрать и решить. Работаю на Delphi 5 и вот наткнулся на такую ситуацию. Есть у меня одна функция и мне её надо вызвать спустя какой-то интервал времени, делаю это с помощью SetTimer. В чём странность? Так вот: в 98-ой винде работает всё нормально. В XP функция таймера срабатывает дважды, а в 2000-ой мало того что срабатывает функция дважды, так после второго завершения программа вылетает с исключением "Access violation", притом не важно что выполняется в функции(процедуре) вызываемой по таймеру. Приведу приметивнейший пример
Проведя некоторые исследования, я заметил такую особенность, если число параметров в вызываемой функции не превышает 3, то такой ситуации не возникает(из ассемблерного кода видно, что если в функции большех трёх параметров, то 4-ый и последующие уже передаются не через регистры, а через стэк). Ещё одна особенность, если процедуру MyFunc вызывать с соглашение stdcall, то тоже всё нормально. Очень важно узнать почему так? Может здесь какая-то несовместимость Delphi 5 и Windows 2000(и выше)? И как тогда выкручиваться при использовании SetTimer в Delphi 5, так как программа должна быть универсальной и работать как под 98-ой, как под 2000-ой и др одинаково? |
| Автор: Palladin 26.5.2007, 00:58 | ||
Короче первое что пришло на ум то и пишу, вообще заводиш глобальную переменную к примеру x типа integer, и там же присваеваеш её начальное значение 0, после этого в условие таймера пишеш
Покатит Добавлено через 25 секунд Тогда будет выполнятся лиш один раз Добавлено через 1 минуту и 22 секунды Так же я не вижу весь код, да и задачи твоей команды, но принцип тот же Добавлено через 1 минуту и 53 секунды Отпиши получилось или нет |
| Автор: Lexicss 26.5.2007, 01:09 | ||
| Ну логика решения проблемы понятна, но всё же мне очень важно узнать почему функция вызывается дважды мгновенно(притом ещё и вылетаю в исключение). Это ж ведь ненормально. А весь код и не нужен, он на самом деле громоздкий, а сама суть здесь изложена в этом коде, здесь такая же ситуация получается. Могу весь код выложить этой ситуации, дабы можно было его скопировать и проверить у себя.
|
| Автор: Alexeis 26.5.2007, 01:12 |
| А чем компонент TTimer не угодил? |
| Автор: Palladin 26.5.2007, 01:14 |
| Хм, ну почему эт конечно хороший вопрос, ответа на него у мя нет, может быть функция settimer юзает какието функции Windows а в XP они несколько отличны от одноименной в 98 и др. вообщем ответа у меня нет, решение есть и я его тееб отписал Добавлено через 1 минуту и 40 секунд Да-да Алексей прав, юзай таймер в конце enabled в false да и все, но впринципе это лиш альтернатива моего метода, хотя скорее наоборот |
| Автор: Lexicss 26.5.2007, 01:46 | ||||
Дело в том что программу писал не я, я дорабатываю, следует оставлять всё так как было задумано разработчиком. Притом в 98-ой всегда всё было нормально, а как перешли на 2000-ую вот такая хрень вылезла.
Вот этого кстати не знал. А почему? Совет, впринципе правильный, но тогда напрашивается вопрос почему в 98-ой всё работает нормально без stdcall. Я вот слышал об этом соглашении что его обычно применяют в описаниях API-функций. Я, наверное, задаю слишком много вопросов. Просто моей задачей стоит не решить конкретную ситуацию і забыть о ней, а именно разобраться почему так получается. Возможно, разобравшись в этом я(да и не тока я) смогу решить и другие проблемы, где есть такое же, но жучки ещё не дали о себе знать. Но всё равно спасибо за советы. Если кто-то что-то ещё знает об этом, пишите. Поделюсь ещё своими наблюдениями. Если изменить код, подавать в MyFunc не 4, а 3(например) параметра, то тогда всё нормально, работает без всяких повторных вызовов и исключений, и stdcall не нужен. Разбирая эти две ситуации в ассемблерном коде обнаружил - (в 4-х параметровой |
| Автор: MetalFan 26.5.2007, 09:16 | ||
| а зачем извраты такие? все системные callback-функции, как уже говорилось, должны быть с директивой stdcall. наверняка это просто случайность. выскажу свои аргументы... вот выдержки из хелпа:
из чего делаем следующие выводы: по умолчанию в делфи используется способ передачи до трех параметров через регистры процессора (директива register). параметры передаются слева направо. в системе по умолчанию используется способ передачи, при котором параметры передаются через стэк, порядок параметров справа налево. соотв. при обозначении в твоей функции трех параметров и без указания stdcall. внутрь попадает абсолютно ничего не значащие значения регистров. а если указано 4 параметра, то последний извлекается из стэка... чем его видимо и рушит... |
| Автор: Lexicss 27.5.2007, 10:15 |
| MetalFan, спасибо. Вопрос почти решён. Остатётся только непонятка, почему работает в 98-ой без stdcall??? Притом программа работает уже давно(более 5 лет). |
| Автор: Yanis 27.5.2007, 10:26 | ||
Это так же как и с 98-м -- куча кода, но почему он работает непонятно |
| Автор: Lexicss 28.5.2007, 22:21 |
| Как я понял из вышеизложенных постов: Моя процедура MyFunc является callback API-шной и следовательно нуждается в директиве stdcall. Если я понял что-то не так - поправьте, пожалуйста. Но всё же остаётся открытым вопрос, почему в Windows 98 эта функция работатет нормально без stdcall, хоть в ней и больше 3-х параметров? Может ещё какие будут варианты объяснения кроме случайности? Если кто что толкового подскажет, буду признателен. ;) |