简体   繁体   English

TDataset与DBGrid的线程竞赛

[英]TDataset thread races with DBGrid

I made TDataset descendant asynchronous, instead of sleep or ProcessMessages in main thread it works by events from network thread. 我使TDataset后代成为异步的,而不是主线程中的sleepProcessMessages ,它由网络线程中的事件起作用。 So when Recordset is ready it calls 因此,当Recordset准备就绪时,它将调用

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

It works, but sometime I have issues with GetRecord by Open called from this thread and DBGrid's GetFieldData called from main thread by DBGrid's DrawCells from Form's ProcessMessages. 它的工作原理,但有时我有问题GetRecord通过Open从这个线程和DBGrid中的所谓GetFieldData通过的DBGrid实现主营线程调用DrawCells从窗体的ProcessMessages。 By logging both functions I see 通过记录两个功能,我看到了

[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   |  ........

and on break by assert when ActiveBuffer column data is nil I can see that DBGrid attempts to read row higher than GetRecord readed into own internal FBuffers. 当ActiveBuffer列数据为nil时断言,我可以看到DBGrid尝试读取的行比读取到自己内部FBuffers中的GetRecord高。 For example if assertion fired at GetFieldData row 3 - FBuffers filled up to row 2 from total 36 rows available in Recordset. 例如,如果在GetFieldData第3行触发断言-FBuffers从Recordset中可用的总共36行填充到第2行。 When I debugging step by step GetRecord with F8 there is no errors utnil I press F9 and get assertion at another record. 当我用F8逐步调试GetRecord ,没有错误,我按F9并在另一条记录中声明。

I'm not quite understand how exactly DBGrid works with TDataset (even stack trace is huge), but can this thread races be solved? 我不太了解DBGrid如何与TDataset一起TDataset (即使堆栈跟踪很大),但是可以解决此线程TDataset用问题吗?

Solution was quite simple: since data in TDataset's FBuffers (from Data.DB) filled with 0 if not initialized it is possible to find filled ActiveBuffer by GetRecord or not by adding yet another marker byte into record and assigning not 0 in GetRecord. 解决方案非常简单:由于TDataset的FBuffers中的数据(来自Data.DB)如果未初始化则填充为0,因此可以通过GetRecord查找填充的ActiveBuffer,也可以通过在记录中添加另一个标记字节并在GetRecord中不分配0来找到。 So if DBGrid attempts to read uninitialized data I checking marker in GetFieldData, if 0 result false and exit. 因此,如果DBGrid尝试读取未初始化的数据,我将检查GetFieldData中的标记,如果0结果为false并退出。 Since DBGrid extracting data to same cells more than once I still have it filled with proper data. 由于DBGrid多次将数据提取到相同的单元格中,因此我仍然用适当的数据填充了该数据。 It is workaround but it works. 这是解决方法,但可以。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM