Форум: "Основная";
Текущий архив: 2006.09.03;
Скачать: [xml.tar.bz2];
ВнизПотокозащищенный список строк Найти похожие ветки
← →
Лапыч © (2006-07-20 11:15) [0]Покопавшись в VCL и посмотрев класс TStringList, я заметил, что практически перед каждым изменением списка вызывается метод Changing, а после изменения - метод Changed. Решил сделать так:
interface
type
TThreadSafeStringList=class(TStringList)
private
fLocker: TCriticalSection;
protected
procedure Lock;
procedure Unlock;
procedure Changed; override;
procedure Changing; override;
function Get(Index: Integer): string; override;
function GetObject(Index: Integer): TObject; override;
function GetCount: Integer; override;
function GetCapacity: Integer; override;
procedure SetCapacity(NewCapacity: Integer); override;
public
constructor Create;
destructor Destroy; override;
end;
implementation
constructor TThreadSafeStringList.Create;
begin
fLocker:=TCriticalSection.Create;
end;
destructor TThreadSafeStringList.Destroy;
begin
inherited;
fLocker.Free;
end;
procedure TThreadSafeStringList.Lock;
begin
fLocker.Enter;
end;
procedure TThreadSafeStringList.Unlock;
begin
fLocker.Leave;
end;
procedure TThreadSafeStringList.Changing;
begin
Lock;
inherited;
end;
procedure TThreadSafeStringList.Changed;
begin
inherited;
Unlock;
end;
function TThreadSafeStringList.Get(Index: Integer): string;
begin
Lock;
try
Result:=inherited Get(Index);
finally
Unlock;
end;
end;
function TThreadSafeStringList.GetObject(Index: Integer): TObject;
begin
Lock;
try
Result:=inherited GetObject(Index);
finally
Unlock;
end;
end;
function TThreadSafeStringList.GetCount: Integer;
begin
Lock;
try
Result:=inherited GetCount;
finally
Unlock;
end;
end;
function TThreadSafeStringList.GetCapacity: Integer;
begin
Lock;
try
Result:=inherited GetCapacity;
finally
Unlock;
end;
end;
procedure TThreadSafeStringList.SetCapacity(NewCapacity: Integer);
begin
Lock;
try
inherited;
finally
Unlock;
end;
end;
Один поток постоянно добавляет строки в список, другой их удаляет в цикле:var
S: string;
begin
while ThreadSafeStringList.Count>0 do
begin
S:=ThreadSafeStringList[0];
DoSomething(S);
ThreadSafeStringList.Delete(0);
end;
end;
При выполненииS:=ThreadSafeStringList[0];
очень редко, но все же происходит Access Violation.
← →
umbra © (2006-07-20 11:40) [1]может быть, стоит перекрыть и метод
Delete
?procedure TStringList.Delete(Index: Integer);
begin
if (Index < 0) or (Index >= FCount) then Error(@SListIndexError, Index);
Changing;
Finalize(FList^[Index]);
Dec(FCount); // мне кажется, что дело в этой строке
if Index < FCount then
System.Move(FList^[Index + 1], FList^[Index],
(FCount - Index) * SizeOf(TStringItem));
Changed;
end;
← →
Лапыч © (2006-07-20 11:47) [2]2umbra:
Обоснуйте, пожалуйста, своё предположение.
Спасибо.
← →
umbra © (2006-07-20 11:59) [3]да, похоже я вспылил :)
надо подумать. Присвоение и удаление строк происходят только в одном месте, показанном Вами? А исключение - именноEAccessViolation
?
← →
Slym © (2006-07-20 13:31) [4]TThreadSafeStringList=class
private
fLocker: TCriticalSection;
FStringList:TStringList;
public
constructor Create;
destructor Destroy; override;
function Lock:TStringList;
procedure Unlock;
end;
implementation
constructor TThreadSafeStringList.Create;
begin
fLocker:=TCriticalSection.Create;
FStringList:=TStringList.Create;
end;
destructor TThreadSafeStringList.Destroy;
begin
FStringList.Free;
fLocker.Free;
inherited;
end;
function TThreadSafeStringList.Lock:TStringList;
begin
fLocker.Enter;
result:=FStringList;
end;
procedure TThreadSafeStringList.Unlock;
begin
fLocker.Leave;
end;
← →
Slym © (2006-07-20 13:32) [5]
var
S: string;
StringList:TStringList;
begin
StringList:=ThreadSafeStringList.Lock;
try
while ThreadSafeStringList.Count>0 do
begin
S:=ThreadSafeStringList[0];
DoSomething(S);
ThreadSafeStringList.Delete(0);
end;
finally
ThreadSafeStringList.UnLock;
end;
end;
← →
Slym © (2006-07-20 13:33) [6]сори...
var
S: string;
StringList:TStringList;
begin
StringList:=ThreadSafeStringList.Lock;
try
while StringList.Count>0 do
begin
S:=StringList[0];
DoSomething(S);
StringList.Delete(0);
end;
finally
ThreadSafeStringList.UnLock;
end;
end;
← →
umbra © (2006-07-20 13:43) [7]2 Slym ©
IdThreadSafe? :)
← →
Лапыч © (2006-07-20 15:32) [8]2Slym:
Потокозащищенный класс TThreadSafeStringList (впрочем, как и все полностью потокозащищенные классы) скрывают (инкапсулируют, если хотите) реализацию механизма доступа к данным. Вызов методов Lock и Unlock должен происходить автоматически при вызове других методов, грозящих ошибкой совместного и одновременного (в терминах вытесняющей многозадачности) доступа к данным.
← →
Slym © (2006-07-21 05:03) [9]И что ты меня учишь? TThreadList посмотри.
Где у тебя здесь защита?var
S: string;
begin
while ThreadSafeStringList.Count>0 do
begin
S:=ThreadSafeStringList[0];
DoSomething(S);
ThreadSafeStringList.Delete(0);
end;
end;
пример:
Поток 1 зашел в
while ThreadSafeStringList.Count>0 do
begin
и был остановлен до
S:=ThreadSafeStringList[0];
поток 2 получил управление и сделал
ThreadSafeStringList.Clear;
поток 1 продолжил выполнение
S:=ThreadSafeStringList[0];
но ожидаемого нулевого элемента уже нету :) вот тебе и Лапыч © (20.07.06 11:15)происходит Access Violation.
← →
Slym © (2006-07-21 05:05) [10]Твой класс защищает вызовы внутри методов класса, но не защищает между ними :(
← →
Лапыч © (2006-07-24 09:30) [11]Всё уже - разобрался с этим. Всем спасибо за внимание и понимание:)
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.09.03;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 1.512 c