Ошибка при выполнении запроса из потока

Access Violation, некорректное выполнение запросов или вызовов API, ошибки утилит командной строки, в общем все, что вам мешает работать

Модераторы: kdv, dimitr

Yaral
Сообщения: 18
Зарегистрирован: 12 фев 2006, 13:00

Ошибка при выполнении запроса из потока

Сообщение Yaral » 10 авг 2006, 11:33

У меня имеется запрос, который выполняется в потоке который запускается по таймеру раз в 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. Почему ругается на транзакцию когда я ее запустил...

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 10 авг 2006, 12:24

http://www.ibase.ru/devinfo/ibx.htm. Раздел TIBDataSet.

Yaral
Сообщения: 18
Зарегистрирован: 12 фев 2006, 13:00

Сообщение Yaral » 10 авг 2006, 12:37

Вообще я использую FIB PLUS, и компонент TpFIBStoredProc
И в данной статье ничего не нашел по моей проблемме...

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 10 авг 2006, 12:42

Пардон, опечатался. Раздел TIBDatabase.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 10 авг 2006, 12:42

Так я не понял: запрос в потоке или по таймеру? Где идет подключение? Что-то ты явно накривил с синхронихацией.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 10 авг 2006, 13:04

"Я сделал классную вещь, завернул в поток и она перестала работать. Почему?"
А насчёт написать, как именно работаешь коннектом к базе, с транзакциями, в каком месте что делаешь? Можно с примером кусочков кода.
Иначе получаются мысли вслух.

Yaral
Сообщения: 18
Зарегистрирован: 12 фев 2006, 13:00

Сообщение Yaral » 10 авг 2006, 13:04

CyberMax писал(а):Пардон, опечатался. Раздел TIBDatabase.
И что там написано? У меня отдельное подключение на основную программу и на поток, подключения не локальные, я об этом в начале писал.

Поток создается по таймеру.
Синхронизация ничего не делает, только включает таймер обратно. Таймер при срабатывании отключается что бы не создать два потока одновременно.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 10 авг 2006, 13:08

Вот интересно - когда-нибудь люди научатся указывать версию используемого сервера? А в вопросах о многопоточности - ещё и клиента?

Yaral
Сообщения: 18
Зарегистрирован: 12 фев 2006, 13:00

Сообщение Yaral » 10 авг 2006, 13:16

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; все будет прекрасно работать, так как поток никогда не выполниться и таймер собственно тоже больше не будет срабатывать.

Yaral
Сообщения: 18
Зарегистрирован: 12 фев 2006, 13:00

Сообщение Yaral » 10 авг 2006, 13:18

Merlin писал(а):Вот интересно - когда-нибудь люди научатся указывать версию используемого сервера? А в вопросах о многопоточности - ещё и клиента?
Совсем забыл FB 1.5.0.4306

Доступ через FIB PLUS 6.25

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 10 авг 2006, 13:25

Рановато ты таймер перезапускаешь...
Уверен что задействованными подключением и транзакцией никто больше не пользуется?
Я бы лично не создавал/завершал поток каждый раз, а будил его event-ом... Да и соответствующие компоненты бы прямо в нем создал. Для надежности.

Yaral
Сообщения: 18
Зарегистрирован: 12 фев 2006, 13:00

Сообщение Yaral » 10 авг 2006, 13:31

Dimitry Sibiryakov писал(а):Рановато ты таймер перезапускаешь...
Уверен что задействованными подключением и транзакцией никто больше не пользуется?
Да вроде не должны, я же это подключение и транзакцию только для потока и использую. Поток в синхранизации таймер включил и через 5 сек только таймер сработает...

Сейчас заметил что если в Delphi установить точку останова на срабатывание таймера то на второй третьей сработке ошибка и вылазиет... т.е. практически сразу. А если в TFIBQueryThread.Execute; поставить точку останова, а со сработки таймера убрать и по F9 продолжать то не виснет...

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 10 авг 2006, 13:43

приведенную ссылку внимательно читал?

Yaral
Сообщения: 18
Зарегистрирован: 12 фев 2006, 13:00

Сообщение Yaral » 10 авг 2006, 13:48

kdv писал(а):приведенную ссылку внимательно читал?
Да, сейчас еще раз прочитал, и?

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 10 авг 2006, 13:52

Брось чудить с включением/отключением таймера. И вообще брось таймер. Делай как я сказал выше: постоянно спящий поток буди event-ом.

Yaral
Сообщения: 18
Зарегистрирован: 12 фев 2006, 13:00

Сообщение Yaral » 10 авг 2006, 14:05

Dimitry Sibiryakov писал(а):Брось чудить с включением/отключением таймера. И вообще брось таймер. Делай как я сказал выше: постоянно спящий поток буди event-ом.
А чем таймер плох?
В том то и дело что event-ом не могу, этот поток по идее должен запихивать в БД данные если в ней никаких действий не происходит... т.е. с оборудования поступают данные, я их пишу в базу. При записи в базу в специальную таблицу заносяться записи указывающие в какой срок должен поступить очередной сигнал. Так вот если он не поступает то мне нужно вставить данные... что то типа "нет сигнала от датчика"... А если данные не поступают то собственно и в таблицу ничего не пишеться и event неоткуда создавать

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 10 авг 2006, 14:07

Таймер плох тем что может запустить два потока подряд, что, похоже, у тебя и происходит. И это было бы ничего, используй они (потоки) только "внутренние" ресурсы, но они же используют компоненты на форме...
Чудик, я говорю не про IB event, а про Win32 event. Есть такая штука удобная для межпоточного взаимодействия.

Yaral
Сообщения: 18
Зарегистрирован: 12 фев 2006, 13:00

Сообщение Yaral » 10 авг 2006, 14:35

Dimitry Sibiryakov писал(а):Таймер плох тем что может запустить два потока подряд, что, похоже, у тебя и происходит. И это было бы ничего, используй они (потоки) только "внутренние" ресурсы, но они же используют компоненты на форме...
Чудик, я говорю не про IB event, а про Win32 event. Есть такая штука удобная для межпоточного взаимодействия.

Так он же отключается пере созданием потока... и включается в синхронизации поток то завершается уже... по краайней мере 5 сек есть на последнюю операцию в потоке

Ну во всяком случае спасибо, попробую посмотреть в сторону Win32 event

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 10 авг 2006, 14:40

по краайней мере 5 сек есть на последнюю операцию в потоке
Может есть а может нет. Кто знает каких багов ты насажал в код... А как они взаимодействуют с борландовскими... А те с микрософтовскими...
С потоками вообще тщательней надо, а уж потоки+таймер - вообще термоядерная смесь.

mdfv
Сообщения: 119
Зарегистрирован: 23 май 2006, 15:53

Сообщение mdfv » 10 авг 2006, 14:51

Может таймер лучше включать в событиии потока OnTerminate?

Ответить