Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Synchronisierung verschiedener Threads


HenryHux - Do 17.02.11 21:57
Titel: Synchronisierung verschiedener Threads
Hi, ich zerbreche mir den Kopf wie ich an das Problem herangehen soll.
Und zwar habe ich ein paar Threads, die eine Prozedur ausführen sollen, jedoch erst wenn sie von keinem anderen Thread benutzt wird.
Also praktisch eine Warteschlange. Mir würde sowas wie globale Variablen einfallen, ist aber denke ich noch ausbaufähig =)
Wie geht man am besten an sowas dran?

Lg


jaenicke - Do 17.02.11 22:01

Dafür eignen sich z.B. critical sections:
http://msdn.microsoft.com/en-us/library/ms682608(v=vs.85).aspx

Ob das die beste Lösung ist, hängt davon ab was da passieren soll. ;-)


HenryHux - Do 17.02.11 22:19

Soll ja nicht die beste Lösung sein, soll nur klappen :D
Also müsste ich hier eine globale Variable machen, die ich dann innerhalb der CriticalSection veränder?
Kann man in einer CriticalSection denn auch Funktionen ausführen?
Sozusagen dass ich ca 4 Threads habe, ich eine Integer Variable anlege, welche angibt welcher Thread als nächster dran ist bzw. welcher gerade am arbeiten ist. Der Laufende Thread setzt diese Variable dann auf 0, wenn er fertig ist und der nächste kann dann wieder über die CriticalSection den Wert ändern, indem er zb in einer Schleife solange wartet bis die Variable 0 ist. Da gäbe es dann aber auch Probleme, die ich selber nicht richtig begreife und nicht in Worte gefasst bekomme :D
Habt ihr Tipps?

Lg


Narses - Do 17.02.11 23:38

Moin!

Ich glaube du suchst eher einen Semaphor [http://edn.embarcadero.com/article/29908]. :idea:

Wozu du allerdings 4 Threads hast, wenn doch immer nur einer aktiv ist, das müsstest du glaub ich nochmal erklären... :? :nixweiss:

cu
Narses


Steve1024 - Fr 18.02.11 00:08

oder du schaust mal in der msdn nach interlockedexchange
damit ist zb die Thread-Sicherheit im TInterfacedObject realisiert.

Hoffe das ist sowas wie du suchst.

lg


HenryHux - Fr 18.02.11 14:25

Erstmal danke für die Antworten, da habe ich ja kräftig was zum lesen :D
Also erstmal wofür ich das brauche, ich habe Threads die verschiedene Dinge berechnen und dann eine Funktion aufrufen, die aber nicht simultan benutzt werden kann.
Dafür so etwas wie eine Warteschlange. Das Konzept wird auf jeden Fall noch überarbeitet, aber jetzt habe ich den Stolz das noch zu schaffen :D
Zu den Semaphoren. Wie werde die genau benutzt bzw wie funktionieren die?
Habe mir mal die Demo dazu angeguckt und den Text mal angelesen.
Die Demo sah vielversprechend aus.
Ich habe mal versucht das grob nachzubauen.

Das ist bis jetzt draus geworden:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
  TTestThread = class(TTHread)
  private
    FSleepDuration: Integer;
    FWaitForDuration: Integer;
  protected
    procedure execute; override;
  public
    property SleepDuration: Integer write FSleepDuration;
    property WaitForDuration: Integer write FWaitForDuration;
  end;

var
  Form1: TForm1;
  Semaphore : THandle;

implementation

{$R *.dfm}

procedure KannNurEinmalGleichzeitigBenutztWerden; forward;

procedure TTestThread.Execute;
var
  WaitResult: Integer;
begin
  WaitResult := WaitForSingleObject(Semaphore, FWaitForDuration);
  sleep(FSleepDuration); //wait until releasing semaphore
  ReleaseSemaphore(Semaphore, 1nil);
  KannNurEinmalGleichzeitigBenutztWerden;
end;

procedure KannNurEinmalGleichzeitigBenutztWerden;
begin
  showmessage('n/a');
end;

procedure TForm1.FormCreate(Sender: TObject);
var Threads : array [1..5of TTestThread;
    i : integer;
begin
  for i := 1 to 5 do
  begin
    Threads[i] := TTestThread.Create;
    with Threads[i] do
    begin
       FreeOnTerminate := True;
       SleepDuration := 2000;
       WaitForDuration := INFINITE;
       Resume;
    end;
  end;
end;

initialization
  Semaphore := CreateSemaphore(nil1,1,'');

finalization
  CloseHandle(Semaphore);

end.


Klappt soweit, er führt alle schön nacheinander aus. Aber wie kann ich jetzt immer warten bis der vorherige Thread mit der KannNurEinmalGleichzeitigBenutztWerden; Prozedur fertig ist?
Hoffe, ihr könnt es besser nachvollziehen als ich :D

Lg

Edit : Hat geklappt, danke! Irgendwann ist mir aufgefallen, dass der Release vor der Prozedur stand.


bummi - Fr 18.02.11 21:36


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TTestThread.Execute;

begin
  WaitForSingleObject(Semaphore, INFINITE);
  KannNurEinmalGleichzeitigBenutztWerden;
  ReleaseSemaphore(Semaphore, 1nil);
end;