2014-01-11 7 views
0

Я сделал TDataset потомком асинхронным, а не sleep или ProcessMessages в основном потоке он работает событиями из сетевой нити. Поэтому, когда Recordset готов он называетTDataset нить гонки с DBGrid

procedure TMySqlQuery.OrdinalOnDataReady(Sender: TObject); 
begin 
    AddToLog('OrdinalOnDataReady'); 
    FDataAvailable := true; // used in IsCursorOpen 
    inherited Open; 
    if Assigned(FParentOnDataReady) then 
     FParentOnDataReady(self); 
end; 

Это работает, но иногда у меня есть проблемы с GetRecord по Open вызываемым из этой нити и DBGrid-х GetFieldData вызывается из основного потока с помощью DBGrid-х DrawCells из ProcessMessages формы. Входя обе функции я вижу

[17:10:39] RecordToBuffer row 0 
[17:10:39] len = 17 buf : 
00 E0 10 C3 00 0A 00 00 00 F0 10 C3 00 0B 00 00 | .ïœ.ï“.....ÿ€.ï“.... 
00 | . 
[17:10:40] RecordToBuffer row 1 
[17:10:40] len = 17 buf : 
00 00 FF C3 00 25 00 00 00 10 11 C3 00 0B 00 00 | ..ÿï“.%.....ï“.... 
00 | . 
[17:10:40] ActiveBuffer 
[17:10:40] len = 17 buf : 
00 E0 10 C3 00 0A 00 00 00 F0 10 C3 00 0B 00 00 | .ïœ.ï“.....ÿ€.ï“.... 
00 | . 
... 
more ActiveBuffer 
... 
[17:10:40] ActiveBuffer 
[17:10:40] len = 17 buf : 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................ 
00 | . 
[17:10:40] len = 8 buf : 
00 00 00 00 00 00 00 00 | ........ 

и на разрыв с помощью утверждают, когда данные столбца ActiveBuffer равна нулю, можно видеть, что DBGrid пытается прочитать строку выше, чем GetRecord прочтенных в собственные внутренние FBuffers. Например, если утверждение было начато с GetFieldData, строка 3 - FBuffers, заполненная до строки 2 из 36 строк, доступных в наборе записей. Когда я отлаживаю шаг за шагом GetRecord с F8, нет ошибок utnil Я нажимаю F9 и получаю утверждение в другой записи.

Я не совсем понимаю, как именно DBGrid работает с TDataset (даже трассировка стека огромна), но можно ли решить эту цепочку?

+0

Доступ к TDataSet из двух потоков одновременно не допускается. TDataSet не является потокобезопасным. –

+1

У Джоанны Картер был хороший набор статей о внутренностях TDataSet. Может быть, вы все еще можете их найти где-то .... Что я помню из своего опыта Delphi 5 с TDbf, элементы управления, поддерживающие db, заботятся только о количестве буферов, поэтому, если вы, например, сообщили, что у вас есть 10 для подсчета буферов - контроль свободен читать их все. Если ваши буферы не готовы - тогда не сообщайте, что у вас есть десять буферов. –

+0

@ Arioch'The - и где статья Joannas? – Branko

ответ

0

Решение было довольно простым: поскольку данные в FBuffers TDataset (из Data.DB), заполненные 0, если не инициализированы, можно найти заполненный ActiveBuffer с помощью GetRecord или нет, добавив еще один маркерный байт в запись и присвоив не 0 в GetRecord. Итак, если DBGrid пытается прочитать неинициализированные данные, я проверяю маркер в GetFieldData, если 0 result false и exit. Поскольку DBGrid извлекает данные в одни и те же ячейки более одного раза, я все еще заполняю их соответствующими данными. Обходной путь, но он работает.

Смежные вопросы