TDataset线程与DBGrid竞争

时间:2014-01-11 15:52:15

标签: multithreading delphi tdataset

我使TDataset后代异步,而不是主线程中的sleepProcessMessages,它来自网络线程的事件。因此,当Recordset准备就绪时,它会调用

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来自Form的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从Recordset中可用的总共36行填充到第2行。当我用F8逐步调试GetRecord时,没有错误,我按F9并在另一条记录上获得断言。

我不太明白DBGrid究竟是如何与TDataset一起工作的(即使堆栈跟踪很大),但这个线程可以解决吗?

1 个答案:

答案 0 :(得分:0)

解决方案非常简单:由于TDataset的FBuffers(来自Data.DB)中的数据如果没有初始化则填充0,可以通过GetRecord找到填充的ActiveBuffer,或者通过将另一个标记字节添加到记录中并在GetRecord中指定不为0 。 因此,如果DBGrid尝试读取未初始化的数据,我会检查GetFieldData中的标记,如果0结果为false则退出。由于DBGrid不止一次将数据提取到相同的单元格,我仍然用它填充了适当的数据。 这是解决方法,但它确实有效。