Synchronizacja wątków

0

Kłopot wygląda tak:

2 wątki: główny GUI + wątek gniazdka (pochodna TServerClientThread)

W głównym wątku posiadam dynamicznie tworzony obiekt typu dajmu na to Server zawierający zmienną typu TServerSocket (ten z ScktComp)

Type
Server = class(TObject)
  public
    Name: String;
...
  private
    SS: TServerSocket;
...
End;

ServerSocket jest tworzony dynamicznie; rodzica brak; działa w trybie stThreadBlocking.

W przypadku połączenia z klientem tworzę wątek gniazdka (w zdarzeniu OnGetThread od w.w. ServerSocket) i uruchamiam pętlę odczytu.

procedure Server.GetThread(Sender: TObject; ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread);
Begin
  SocketThread := Czytnik.Create(Self, False, ClientSocket);
End;

Selfa używam, by w wątku gniazdka mieć coś, przez co będę mógł się odwołać do obiektu Server (a w zasadzie do jego właściwości Name)

Mam potrzebę w pętli odczytującej (Czytnik.ClientExecute - wątek gniazdka) uzyskać dostęp do właściwości Name nadrzędnego obiektu Server...

No i właśnie... próbowałem przez

Synchronize 

i jest "AccesViolation"
Próbowałem blokować wątki przez

EnterCriticalSection 

i jest również "AccesViolation"...

Niezbyt uśmiecha mi się ładować do każdego wątku kopię wszystkich właściwości obiektu Server - bo to rozwiązanie najbardziej debilne i zasobożerne (Name to tylko przykładowy jeden z nich, a jest tego trochę)
Może ktoś ma jakąś ideę, jak to przekonfigurować, by miało ręce i nogi? :P
Byłbym wdzięczny :)

0

no to może napisz JAK próbowałeś

0
Unit UServer;
...

Type
Server = class(TObject)
  public
    Name: String;
    procedure Lock;
    procedure unlock;
...
  private
    SS: TServerSocket;
...
End;

Var ThreadLock: TRTLCriticalSection;
    LockVar:TMultiReadExclusiveWriteSynchronizer;

...

Constructor Server.Create(Port:Word; Name: String);
Begin
  Inherited Create;
  Self.Name := Name;

  SS := TServerSocket.Create(nil);
  SS.OnGetThread := SSGetThread;
  SS.ServerType := stThreadBlocking;
  SS.Port := Port;
End;

...

procedure Server.Lock;
begin
  EnterCriticalSection(ThreadLock);
end;

procedure Server.Unlock;
begin
  LeaveCriticalSection(ThreadLock);
end;

...

initialization
  InitializeCriticalSection(ThreadLock);
  LockVar:=TMultiReadExclusiveWriteSynchronizer.Create;

finalization
  DeleteCriticalSection(ThreadLock);
  FreeAndNil(LockVar);
Unit CThread;
...
  CThread= class( TServerClientThread{TThread})
  public
    S: Server;   // Serwer, który utworzył ten wątek - po to, by móc się odwołać do jego metod
...
  end;

...

Constructor CThread.Create(S: Server; CreateSuspended: Boolean; ASocket: TServerClientWinSocket);
Begin
  Inherited Create(CreateSuspended, ASocket);
  Self.S := S;
...
End;

...

Procedure CThread.Blablabla;
Var x: String;
Begin
  S.Lock;   // próbowałem też UServer.LockVar.BeginRead;
  x := S.Name;   // TU JEST PROBLEM - nie ważne czy odpalę Blablabbla przez synchronize, czy dla lock/unlock czy coś innego
  // mogę stąd wywołać metodę serwera, ale chcę, by kod był w wątku klienta - pare wątków może spowolnić to gdy będą próbowały naraz wykonać metodę klienta

  S.Unlock;   // próbowałem też UServer.LockVar.EndRead;
End;
0
  1. nie dałeś najważniejszego - jak tworzysz wątek
  2. postaw sobie w x := S.Name breakpointa i zobacz czy S <> nil bo jeśli dostajesz tam AV to na 99% S jest nil

1 użytkowników online, w tym zalogowanych: 0, gości: 1