2014-01-11 2 views
0

주 스레드에서 sleep 또는 ProcessMessages 대신 TDataset 자손 비동기를 만들었습니다.이 스레드는 네트워크 스레드의 이벤트에서 작동합니다. 레코드가 준비 그래서 때 그것은 작동DBGrid가있는 TDataset 스레드 레이스

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

를 호출하지만 언젠가 나는이 스레드에서 호출 Open에 의해 GetRecord 문제를 가지고 DBGrid를의 GetFieldData DBGrid를의 DrawCells 양식의 ProcessMessages에서에서 메인 쓰레드에서 호출. 내가 DBGrid를 자신의 내부 FBuffers로 읽혀질 수 GetRecord보다 높은 행을 읽으려고 것을 볼 수있다 전무 ActiveBuffer 열 데이터 인 경우 두 기능을 로그인하여 나는 어설으로

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

및 휴식

를 참조하십시오. 예를 들어 assertion이 GetFieldData 행 3에서 시작된 경우 - FBeters는 Recordset에서 사용할 수있는 총 36 개의 행에서 2 번째 행까지 채 웁니다. 내가 F8과 함께 GetRecord 단계로 디버깅 할 때 오류가 없습니다 utnil 나는 F9 키를 눌러 다른 레코드에서 주장을 얻을.

나는 정확히 DBGridTDataset (심지어 스택 추적도 거대합니다)과 어떻게 작동하는지 이해하지 못하고 있지만이 스레드 레이스가 해결 될 수 있습니까?

+0

두 스레드에서 TDataSet에 동시에 액세스 할 수 없습니다. TDataSet은 스레드로부터 안전하지 않습니다. –

+1

Joanna Carter는 TDataSet 내부에 대한 훌륭한 기사를 가지고있었습니다. 어쩌면 당신은 여전히 ​​어딘가에 그것들을 찾을 수있을 것입니다 ... TDbf를 가진 나의 델파이 5 경험에서 기억하는 것에 대해 db- aware 컨트롤은 오직 버퍼의 수만을 고려합니다, 그래서 여러분이 버퍼 수에 대해 10을 가지고 있다고보고한다면 - 컨트롤은 모든 것을 자유롭게 읽을 수 있습니다. 버퍼가 준비되지 않았다면 10 개의 버퍼가 있다는 것을보고하지 마십시오. –

+0

@ Arioch'The - Joannas 문서는 어디에 있습니까? – Branko

답변

0

해결 방법은 간단합니다. TDataaset의 FBuffers (Data.DB)의 데이터가 초기화되지 않은 경우 0으로 채워지기 때문에 GetRecord에 의해 채워진 ActiveBuffer를 찾을 수도 있고 레코드에 다른 마커 바이트를 추가하고 0을 할당하지 않아도됩니다 GetRecord. DBGrid가 초기화되지 않은 데이터를 읽으려고하면 GetFieldData에서 마커를 검사하고 0이면 false가되고 종료됩니다. DBGrid가 동일한 셀에 데이터를 한 번 이상 추출하기 때문에 적절한 데이터로 채워져 있습니다. 해결 방법이지만 작동합니다.