Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Реализация списка в многопоточном приложении


sanx ©   (2009-08-25 03:11:00) 

Создаю класс наследник от TList

type
 PRule = ^TRule;
 TRule = record
   ID: Integer;
   Filter1: AnsiString;
   Filter2: AnsiString;
   // ...
 end;

 TRules = class(TList)
 private
 protected
   procedure Notify(Ptr: Pointer; Action: TListNotification); override;
 public
   constructor Create(DefaultRule: TRule);
   procedure Add(Rule: TRule);
   function Find(ID: Integer): Integer; overload;
   function Find(Filter1, Filter2: AnsiString): Integer; overload;
 end;

implementation

procedure TRules.Add(Rule: TRule);
var
 NewRule: PRule;
begin
 New(NewRule);
 System.Move(Rule, NewRule^, SizeOf(TRule));
 inherited Add(NewRule);
end;

constructor TRules.Create(DefaultRule: TRule);
begin
 Add(DefaultRule);
end;

function TRules.Find(ID: Integer): Integer;
var
 I: Integer;
begin
 Result := -1;
 for I := 0 to Count - 1 do
   if PRule(Items[I])^.ID = ID then begin
     Result := I;
     Break;
   end;
end;

function TRules.Find(Filter1, Filter2: AnsiString): Integer;
var
 I: Integer;
begin
 Result := -1;
 for I := 0 to Count - 1 do
   if (PRule(Items[I])^.Filter1 = Filter1)
     and (PRule(Items[I])^.Filter2 = Filter2) then begin
     Result := I;
     Break;
   end;
end;

procedure TRules.Notify(Ptr: Pointer; Action: TListNotification);
begin
 if Action = lnDeleted then Dispose(Ptr);
 inherited Notify(Ptr, Action);
end;


Но как сделать его потокобезопасным? Изменяется список только из главного VCL-потока. А вот чтение нужно сделать безопасным для нескольких рабочих потоков.


Loginov Dmitry   (2009-08-25 21:20:00) [1]

> Но для меня не совсем понятно почему метод BeginWrite описан
> как функция с результатом Boolean? Из описания не пойму
> ничего. Нужно проверять этот результат? А что делать если
> False?


В VCL нигде этот результат не анализируется. Так что можешь без
проверки результата. Имхо, если вернет False, то считай, что тебе
удалось взломать этот самый синхронайзер :)


sanx   (2009-08-25 18:07:00) [2]

Да спасибо, TMultiReadExclusiveWriteSychronizer то что нужно, вот еще нашел http://www.sql.ru/forum/actualthread.aspx?tid=603799
В инете много обсуждений по поводу TMultiReadExclusiveWriteSychronizer и его глючности и дедлоков, и все вроде соглашаются с тем что начиная с Delphi 7 этот класс стал вести себя очень хорошо. Но для меня не совсем понятно почему метод BeginWrite описан как функция с результатом Boolean? Из описания не пойму ничего. Нужно проверять этот результат? А что делать если False?


Leonid Troyanovsky   (2009-08-25 10:29:00) [3]


> Kolan ©   (25.08.09 10:00) [3]

> Есть TThreadList — как раз потоко безопасный список.

Читателей много - писатель один. Как раз для этого [2].

Правда, его обновленную в D5? версию не исследовал,
а раньше замечен был в дедлоках.

--
Regards, LVT.


Kolan   (2009-08-25 10:00:00) [4]

Есть TThreadList— как раз потоко безопасный список.


MBo   (2009-08-25 05:48:00) [5]

TMultiReadExclusiveWriteSychronizer можно использовать


sanx   (2009-08-25 03:28:00) [6]

Можно использовать Критические секции для блокировки списка при любом доступе к нему, но читать то можно позволить и нескольким сразу, а изменения не часто делаются, их через GUI пользователь делает. Вот в чем для меня сложность.

А вот кое-какие мысли есть:
- Использовать обьект ядра - событие, при любом изменении списка устанавливать в занято.
- Добавить метод Wait. При попытке чтения вызвать метод Wait, который будет ждать событие из первого пукта, если нужно конечно, иначе сразу вернет результат.

Но тут проблема: как начать изменения, именно в тот момент когда никто не читает? Еще одно событие? ) Которое уже устанавливается при попытки чтения? :)


Наверх

Титульная страница Поиск, карта сайта Написать письмо