| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Как запустить процедуру таймера в отдельном потоке |
| Автор: mr_smit 13.3.2010, 15:05 | ||
По событию таймера, раз в 5 сек, происходит запись данных в СОМ порт, что подвешивает программу. Как запустить процедуру таймера в отдельном потоке?
|
| Автор: samsamich 13.3.2010, 16:22 |
| Надо не процедуру таймера запускать в отдельном потоке, а создавать отдельный поток в процедуре таймера.. |
| Автор: Dom 13.3.2010, 18:27 |
| Мне кажется, что это может быть не эффективным, если каждые 5 секунд создавать, запускать и уничтожать поток. Много времени будет уходить. Как вариант, можно приостанавливать поток и возобновлять его каждые 5 секунд. |
| Автор: mr_smit 13.3.2010, 19:31 | ||||||
Во во... Может конечно глупо, но попробовал так:
Ругается на классы... типа не может один класс быть внутри другого. Т.к. у меня есть процедура ReadSensors "внутри таймера".
Можно конечно убрать привязку к TForm1, но тогда "поплывет" весь код... Не работал с потоками раньше. Неужели нельзя создать поток и выполнять процедуру в нем??? |
| Автор: Dom 13.3.2010, 23:17 |
| Если нет опыта работы с потоками, то обязательно к прочтению http://forum.vingrad.ru/forum/topic-60076.html Мне еще MSDN помог в освоении потоков. Так просто с наскоку маловероятно, что получится что-то работающее. |
| Автор: mr_smit 15.3.2010, 10:11 | ||
Спасибо, почитаю. Тем не менее вопрос в силе:
Добавлено через 1 минуту и 23 секунды В двух словах, по простому, с примером, может кто объяснит, пожалуйста. |
| Автор: Snowy 15.3.2010, 12:39 |
| ИМХО, таймер тут вообще не нужен. Создай поток, выполняй в нём запись в порт. После записи засыпай поток на время, оставшееся до следующего момента срабатывания. Например: 0 секунда - пишем данные, это заняло, например, 0.5 секунд 0.5 секунд - интервал 5 секунд, прошлое срабатывание в 0 секунд, сейчас 0.5 секунд. Значит засыпаем на 4.5 секунды - Sleep(4500). 5 секунд - пишем данные...... |
| Автор: Matematik 15.3.2010, 14:21 | ||||
+1 Примерно так
|
| Автор: mr_smit 28.3.2010, 18:10 | ||||
Создал отдельный unit2 для потока:
А в unit1 написал:
Получаю ошибку при создании потока. BMP, PColor и т.д. сделал глобальными в unit1 Добавлено через 2 минуты и 16 секунд EAccessViolation |
| Автор: Alexeis 28.3.2010, 18:24 |
Это говорит лишь о том, что ошибка работы с памятью. Наверняка не синхронизировал доступ к глобальному объекту из разных потоков. Еще варианты дважды удалил или не создал, а пользуешься. |
| Автор: Dom 29.3.2010, 09:31 | ||
А может так создавать объект?
|
| Автор: mr_smit 29.3.2010, 12:33 | ||||||
Я код привел, какая там может быть синхронизация??? Одна процедура Execute. Переменные объявлены в unit1. Ошибка возникает каждый раз при создании. Если бы дело было в синхронизации, то ошибка не всегда бы возникала. Добавлено через 1 минуту и 13 секунд
Не думаю что это поможет. Просто не пойму что тут может быть не правильно, 10 строк кода. |
| Автор: Alexeis 29.3.2010, 12:48 |
Например обращаешься к BMP из 2х потоков одновременно. Вообще, посмотри точку вылета в Call Stack. |
| Автор: Gwire 29.3.2010, 13:39 | ||||
Потоковый таймер с использованием CreateWaitableTimer;
FWaitEvent это объект Event-подобный, стой разницей что он устанавливается сам со строго заданным интервалом. Если процедура Run выполняется дольше установленного времени, то при возврате в Execute FWaitEvent уже будет установлен и следуюций цикл выполнится не замедлительно. Чтобы дождаться следующего сраватывания таймера перед выходом из Run вставить "ResetEvent( FWaitEvent );" Если нужно подождать заданое время, то нужно вместо ResetEvent переустоновить интервал - Interval:= FInterval; Удачи. PS: Dom прав - создавать нужно "от имени" класса а не объекта. То что ты объявишь переменную (указатель на объект), var LCDThead: TLCD, она не станет объектом, это только определит её поведение для компилятора. А любой вызов метода не существуещего объекта даст "EAccessViolation" в том числе и Create Сперва необходимо поместить в переменную значение: LCDThead := TLCD.Create(false). Здесь Create метод класса а не объекта. Тоже самое и в при обащении в свойству объекта BMP.Canvas. Нет BMP:= TBitmap.Create; |
| Автор: mr_smit 29.3.2010, 22:32 | ||||
Помогло. Работает. Только если перемещать форму данные куда то деваются... Если при отправлении начать таскать форму то (например с середины картинки) идет заполнение белым цветом. В процедуре таймера:
и в этой же процедуре в потоке отправка в порт. Т.е. как будто Assign куда то пропадает Вот что у меня получается на данный момент (видео работы моего USB дисплея): http://www.youtube.com/watch?v=5EcmFPGZLvc |