Безопасно ли изменять данные VirtualTreeView из вторичного потока?И если да, я должен использовать критические секции (или даже метод Synchronize)?
Я боюсь, что когда я буду записывать в запись данных VT из другого потока, основной поток тем временем вызывает его перерисовку иэто обновление приведет к чтению одной и той же записи за один раз.Я бы добавил, что я использую только 2 темы в приложении.
Что-то вроде ...
type
PSomeRecord = ^TSomeRecord;
TSomeRecord = record
SomeString: string;
SomeInteger: integer;
SomeBoolean: boolean;
end;
...
var FCriticalSection: TRTLCriticalSection; // global for both classes
...
procedure TMyCreatedThread.WriteTheTreeData;
var CurrentData: PSomeRecord;
begin
EnterCriticalSection(FCriticalSection); // I want to protect only the record
CurrentData := MainForm.VST.GetNodeData(MainForm.VST.TopNode);
with CurrentData^ do // I know, the ^ is not necessary but I like it :)
begin
SomeString := 'Is this safe ? What if VT will want this data too ?';
SomeInteger := 777;
SomeBoolean := True;
end;
LeaveCriticalSection(FCriticalSection);
MainForm.VST.Invalidate;
end;
// at the same time in the main thread VT needs to get text from the same data
// is it safe to do it this way ?
procedure TMainForm.VST_GetText(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var CellText: string);
var CurrentData: PSomeRecord;
begin
EnterCriticalSection(FCriticalSection); // I want to protect only the record
CurrentData := VST.GetNodeData(VST.TopNode);
with CurrentData^ do
begin
case Column of
0: CellText := SomeString;
1: CellText := IntToStr(SomeInteger);
2: CellText := BoolToStr(SomeBoolean);
end;
end;
LeaveCriticalSection(FCriticalSection);
end;
// I'm afraid the concurrent field reading may happen only here with the private VT fields
// FNodeDataSize, FRoot and FTotalInternalDataSize, since I have Node.Data locked by the
// critical sections in the VT events, some of those may be accessed when VT is refreshed
// somehow
function TBaseVirtualTree.GetNodeData(Node: PVirtualNode): Pointer;
begin
Assert(FNodeDataSize > 0, 'NodeDataSize not initialized.');
if (FNodeDataSize <= 0) or (Node = nil) or (Node = FRoot) then
Result := nil
else
Result := PByte(@Node.Data) + FTotalInternalDataSize;
end;
Обновление
У меня естьдобавил критические разделы в код, действительно ли небезопасно вызывать GetNodeData из класса TMyCreatedThread, даже если эта функция возвращает только указатель на запись?
Большое спасибо
С уважением