Страница 1 из 2
Ошибка при выполнении запроса из потока
Добавлено: 10 авг 2006, 11:33
Yaral
У меня имеется запрос, который выполняется в потоке который запускается по таймеру раз в 5 сек. Запрос в потоке выполняется быстро, но на всякий случай перед выполнением его таймер выключается, а затем в процедуре синхронизации включается снова.
Данный запрос просто читает информацию из БД, ничего не изменяя.
Поток использует отдельное подключение (не локальное естественно).
Поток я дописал в программу которая принимает данные с порта и записывает в БД. Она выполняет последовательные (по получению данных) запросы которые добавляют записи в одну таблицу. Эту программу я тестировал довольно долгое время и на максимальной скорости. После этого она работает более пол года и ни одного сбоя.
Так вот я добавил в нее поток и начались глюки... не постоянно, но нет нет так вылезет, раз в несколько часов.
Глюки такого рода:
MainForm.SPAEventInsS
Unsuccessful execution caused by a system error that precludes successful execution of subsequent statement.Error reading data from the conntction
(MainForm.SPAEventInsS - процедура записи данных в таблицу).
Такая же ошибка только с процедурой из потока возникает.
При запуске из Delphi перед этой ошибкой возникает еще и ошибка в которой говориться что транзакция не запущена, хотя я их в данной программе всегда явно запускаю и подтверждаю... их всего 2. Одна в самой программе, другая в потоке.
1. Что это за ошибка?
2. Почему ругается на транзакцию когда я ее запустил...
Добавлено: 10 авг 2006, 12:24
CyberMax
Добавлено: 10 авг 2006, 12:37
Yaral
Вообще я использую FIB PLUS, и компонент TpFIBStoredProc
И в данной статье ничего не нашел по моей проблемме...
Добавлено: 10 авг 2006, 12:42
CyberMax
Пардон, опечатался. Раздел TIBDatabase.
Добавлено: 10 авг 2006, 12:42
Dimitry Sibiryakov
Так я не понял: запрос в потоке или по таймеру? Где идет подключение? Что-то ты явно накривил с синхронихацией.
Добавлено: 10 авг 2006, 13:04
WildSery
"Я сделал классную вещь, завернул в поток и она перестала работать. Почему?"
А насчёт написать, как именно работаешь коннектом к базе, с транзакциями, в каком месте что делаешь? Можно с примером кусочков кода.
Иначе получаются мысли вслух.
Добавлено: 10 авг 2006, 13:04
Yaral
CyberMax писал(а):Пардон, опечатался. Раздел TIBDatabase.
И что там написано? У меня отдельное подключение на основную программу и на поток, подключения не локальные, я об этом в начале писал.
Поток создается по таймеру.
Синхронизация ничего не делает, только включает таймер обратно. Таймер при срабатывании отключается что бы не создать два потока одновременно.
Добавлено: 10 авг 2006, 13:08
Merlin
Вот интересно - когда-нибудь люди научатся указывать версию используемого сервера? А в вопросах о многопоточности - ещё и клиента?
Добавлено: 10 авг 2006, 13:16
Yaral
WildSery писал(а):"Я сделал классную вещь, завернул в поток и она перестала работать. Почему?"
А насчёт написать, как именно работаешь коннектом к базе, с транзакциями, в каком месте что делаешь? Можно с примером кусочков кода.
Иначе получаются мысли вслух.
Код потока:
Код: Выделить всё
type
TFIBQueryThread = class(TThread)
private
procedure Syn;
protected
procedure Execute; override;
public
constructor Create; virtual;
end;
constructor TFIBQueryThread.Create;
begin
inherited
Create(True);
FreeOnTerminate := True;
Resume;
end;
procedure TFIBQueryThread.Execute;
begin
try
MainForm.TrEr.StartTransaction;
MainForm.SpEJouErCheck.ExecProc;
MainForm.TrEr.Commit;
Synchronize(Syn);
except
MainForm.TrEr.Rollback;
end;
end;
procedure TFIBQueryThread.Syn;
begin
MainForm.TmEr.Enabled:=True;
end;
SpEJouErCheck ничего не делает, ничего не возращает, в ней производиться только проверка:
Код: Выделить всё
IF (EXISTS(SELECT * FROM EJER WHERE TS<'NOW')) THEN
BEGIN
END
В блок BEGIN END (хотя и он пустой) она никогда не попадает так как нет в базе таких записей. Предпологалось что она (ХП) будет там операции записи производить... но до этого дело не дошло...
Запускается все это добро таймером:
Код: Выделить всё
procedure TMainForm.TmErTimer(Sender: TObject);
begin
TmEr.Enabled:=False;
TFIBQueryThread.Create;
end;
Вот и все что я добавил в программу...
Если закоментировать TFIBQueryThread.Create; все будет прекрасно работать, так как поток никогда не выполниться и таймер собственно тоже больше не будет срабатывать.
Добавлено: 10 авг 2006, 13:18
Yaral
Merlin писал(а):Вот интересно - когда-нибудь люди научатся указывать версию используемого сервера? А в вопросах о многопоточности - ещё и клиента?
Совсем забыл FB 1.5.0.4306
Доступ через FIB PLUS 6.25
Добавлено: 10 авг 2006, 13:25
Dimitry Sibiryakov
Рановато ты таймер перезапускаешь...
Уверен что задействованными подключением и транзакцией никто больше не пользуется?
Я бы лично не создавал/завершал поток каждый раз, а будил его event-ом... Да и соответствующие компоненты бы прямо в нем создал. Для надежности.
Добавлено: 10 авг 2006, 13:31
Yaral
Dimitry Sibiryakov писал(а):Рановато ты таймер перезапускаешь...
Уверен что задействованными подключением и транзакцией никто больше не пользуется?
Да вроде не должны, я же это подключение и транзакцию только для потока и использую. Поток в синхранизации таймер включил и через 5 сек только таймер сработает...
Сейчас заметил что если в Delphi установить точку останова на срабатывание таймера то на второй третьей сработке ошибка и вылазиет... т.е. практически сразу. А если в TFIBQueryThread.Execute; поставить точку останова, а со сработки таймера убрать и по F9 продолжать то не виснет...
Добавлено: 10 авг 2006, 13:43
kdv
приведенную ссылку внимательно читал?
Добавлено: 10 авг 2006, 13:48
Yaral
kdv писал(а):приведенную ссылку внимательно читал?
Да, сейчас еще раз прочитал, и?
Добавлено: 10 авг 2006, 13:52
Dimitry Sibiryakov
Брось чудить с включением/отключением таймера. И вообще брось таймер. Делай как я сказал выше: постоянно спящий поток буди event-ом.
Добавлено: 10 авг 2006, 14:05
Yaral
Dimitry Sibiryakov писал(а):Брось чудить с включением/отключением таймера. И вообще брось таймер. Делай как я сказал выше: постоянно спящий поток буди event-ом.
А чем таймер плох?
В том то и дело что event-ом не могу, этот поток по идее должен запихивать в БД данные если в ней никаких действий не происходит... т.е. с оборудования поступают данные, я их пишу в базу. При записи в базу в специальную таблицу заносяться записи указывающие в какой срок должен поступить очередной сигнал. Так вот если он не поступает то мне нужно вставить данные... что то типа "нет сигнала от датчика"... А если данные не поступают то собственно и в таблицу ничего не пишеться и event неоткуда создавать
Добавлено: 10 авг 2006, 14:07
Dimitry Sibiryakov
Таймер плох тем что может запустить два потока подряд, что, похоже, у тебя и происходит. И это было бы ничего, используй они (потоки) только "внутренние" ресурсы, но они же используют компоненты на форме...
Чудик, я говорю не про IB event, а про Win32 event. Есть такая штука удобная для межпоточного взаимодействия.
Добавлено: 10 авг 2006, 14:35
Yaral
Dimitry Sibiryakov писал(а):Таймер плох тем что может запустить два потока подряд, что, похоже, у тебя и происходит. И это было бы ничего, используй они (потоки) только "внутренние" ресурсы, но они же используют компоненты на форме...
Чудик, я говорю не про IB event, а про Win32 event. Есть такая штука удобная для межпоточного взаимодействия.
Так он же отключается пере созданием потока... и включается в синхронизации поток то завершается уже... по краайней мере 5 сек есть на последнюю операцию в потоке
Ну во всяком случае спасибо, попробую посмотреть в сторону Win32 event
Добавлено: 10 авг 2006, 14:40
Dimitry Sibiryakov
по краайней мере 5 сек есть на последнюю операцию в потоке
Может есть а может нет. Кто знает каких багов ты насажал в код... А как они взаимодействуют с борландовскими... А те с микрософтовскими...
С потоками вообще тщательней надо, а уж потоки+таймер - вообще термоядерная смесь.
Добавлено: 10 авг 2006, 14:51
mdfv
Может таймер лучше включать в событиии потока OnTerminate?