AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Problem beim Zugriff auf TObjectList aus Threads
Thema durchsuchen
Ansicht
Themen-Optionen

Problem beim Zugriff auf TObjectList aus Threads

Ein Thema von alkan · begonnen am 8. Okt 2008 · letzter Beitrag vom 10. Okt 2008
Antwort Antwort
alkan

Registriert seit: 8. Aug 2008
7 Beiträge
 
#1

Problem beim Zugriff auf TObjectList aus Threads

  Alt 8. Okt 2008, 23:25
Da ich in meinem aktuellen Projekt etliche Probleme mit dem Multithreading habe, habe ich nun ein kleines Testprogramm geschrieben, um dem dem Übel auf den Grund zu gehen. Dabei habe ich eine seltsame Entdeckung gemacht.

Zunächst habe ich einen Sample-Thread geschrieben, der wie folgt aussieht:

Delphi-Quellcode:
TSampleThread= class(TThread)
  TestList: TObjectList;
protected
  procedure Execute; override;
public
  constructor Create; virtual;
end;

constructor TSampleThread.Create;
begin
  inherited Create(False);
  FreeOnTerminate := False;
  TestList := TObjectList.Create;
end;

procedure TSampleThread.Execute;
var j, Rnd: integer;
begin
  j := 1;
  repeat
    Rnd := Random(10);
    inc(j);
  until j = 10;
  Terminate;
end;
Den Thread starte ich nun von einem "Manager" aus, der nichts anderes macht, als bei jedem Aufruf TSampleThread einen freien Slot zuzuweisen und diesen darüber auszuführen. Sind gerade alle 20 Slots besetzt, so wird der Thread nicht ausgeführt.

Delphi-Quellcode:

TThreadManager = class
public
  Thread: array[1..20] of TSampleThread;
  procedure Add;
end;

procedure TThreadManager.Add;
var i: integer; FreeSlot: boolean;
begin
  i := 0;
  FreeSlot := False;
  repeat
    inc(i);
    if Assigned(Thread[i]) = True then
    begin
      if Thread[i].Terminated = True then
        FreeSlot := True;
    end
    else
      FreeSlot := True;
  until (FreeSlot = True) or (i = 20);

  if FreeSlot = True then
    Thread[i] := TSampleThread.Create;
end;
Das ganze klappt bis dahin wunderbar. Auch wenn ich TSampleThread mittels eines TTimer-Objekts durch die Funktion TThreadManager.Add bis zu 1000 Mal pro Sekunde aufrufe, läuft alles wie geschmiert.

Das Problem tritt erst auf, wenn ich im Thread auf ein threadinternes TObjectList-Object zugreife, z.B. auf dessen Eigenschaft Count:

Delphi-Quellcode:
procedure TSampleThread.Execute;
var j, Rnd: integer;
begin
  j := 1;
  repeat
    Rnd := Random(TestList.Count + 10);
    inc(j);
  until j = 10;
  Terminate;
end;
Die einzige Zeile, die ich verändert habe, ist die, wo der Random-Wert bestimmt wird. Ansonsten bleibt alles gleich.
Wenn ich nun aber meinen Thread so wie oben beschrieben sehr oft pro Sekunde ausführe, kommt es früher oder später zum Absturz ("Project1 hat ein Problem festgestellt und muss beendet werden").
Auf den ersten Blick sieht also alles nach einem Synchronizations-Problem aus. Aber daran kann es doch in diesem Fall nicht liegen.
Denn jeder Thread hat sein eigenes TestList-Objekt und greift völlig unabhängig von den anderen exklusiv auf dieses zu!?
Die Threads kommen sich auf keinen Fall beim Zugriff auf TestList in die Quere. Und trotzdem schmiert mein Proggi ab.

Wäre froh um jeden Ratschlag, denn ich finde das ganze einfach zu verwirrend.

Nachtrag: So klappt es...
Delphi-Quellcode:
constructor TSampleThread.Create;
begin
  inherited Create(False);
  FreeOnTerminate := False;
  TestList := TObjectList.Create;
  test := TestList.Count; // = 0
end;

procedure TSampleThread.Execute;
var j, Rnd: integer;
begin
  j := 1;
  repeat
    Rnd := Random(test);
    inc(j);
  until j = 10;
  Terminate;
end;
  Mit Zitat antworten Zitat
Roachford
(Gast)

n/a Beiträge
 
#2

Re: Problem beim Zugriff auf TObjectList aus Threads

  Alt 8. Okt 2008, 23:40
Ein paar Gedanken von mir dazu:

- du gibst nirgendwo die TObjectList Instanz wieder frei aus dem Thread
- du gibst nirgendwo beendete Threads wieder frei
- vergleiche niemals auf true
- warum ist der Constructor des Threads virtuell?
- du benutzt die Terminate Methode falsch, da diese nur das Terminated Flag setzt und somit eine Kennzeichnung für den Nutzer von TThread sein soll, die Execute-Methode zu verlassen.

Und dein Hauptfehler:

- du lässt den Thread sofort loslaufen, und das bevor der Constructor abgearbeitet ist und somit bevor die ObjectList Instanz gebildet wurde.

Zu deinem Edit: alle Member einer Klasse sowie globale Objekte werden auf ordinal 0 initialisiert.

/EDIT: nochmal alle Hinweise umgesetzt:
Delphi-Quellcode:
type
  TSampleThread= class(TThread)
    TestList: TObjectList;
  protected
    procedure Execute; override;
  public
    constructor Create;
    destructor Destroy; override;
  end;

constructor TSampleThread.Create;
begin
  inherited Create(true);
  FreeOnTerminate := False;
  TestList := TObjectList.Create;
  Resume;
end;

destructor TSampleThread.Destroy;
begin
  TestList.Free;

  inherited;
end;

procedure TSampleThread.Execute;
var j, Rnd: integer;
begin
  j := 1;
  while not Terminated and ( j < 10 ) do
  begin
    Rnd := Random(TestList.Count + 10);
    inc(j);
  end;
end;
Delphi-Quellcode:
TThreadManager = class
public
  Thread: array[1..20] of TSampleThread;
  procedure Add;
end;

procedure TThreadManager.Add;
var
  i: integer;
  FreeSlot: boolean;
begin
  i := 0;
  FreeSlot := False;
  repeat
    inc(i);

    FreeSlot := ( assigned(Thread[i]) and Thread[i].Terminated )
                or not assigned(Thread[i]);
  until FreeSlot or (i = 20);

  if FreeSlot then
  begin
    Thread[i].Free;
    Thread[i] := TSampleThread.Create;
  end;
end;
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: Problem beim Zugriff auf TObjectList aus Threads

  Alt 9. Okt 2008, 10:30
Edit X: (also nochmal)

Zitat:
Und dein Hauptfehler:

- du lässt den Thread sofort loslaufen, und das bevor der Constructor abgearbeitet ist und somit bevor die ObjectList Instanz gebildet wurde.
TThread startet den Thread immer suspended, egal welcher Parameter angegeben wird. Am Ende des Constrcutors wird immer die Methode Afterconstruction aufgerufen. Und erst hier wird der Thread ggf. gestartet.
Demnach ist es egal wann welche Variablen initialisiert werden bei TThread. Und oben genanntes ist kein Fehler
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von gsh
gsh

Registriert seit: 24. Okt 2004
1.542 Beiträge
 
Delphi XE Architect
 
#4

Re: Problem beim Zugriff auf TObjectList aus Threads

  Alt 9. Okt 2008, 11:46
Kann es sein das du überhaupt nicht syncronisiert auf den Thread zugreist?
Deswegen kracht es bei dem .Count weil du bei 1000 in der sekunde sehr wahrscheinlich einmal gleichzeitig lesen und schreiben willst
Alex
"Sage nicht alles, was du weißt, aber wisse alles, was du sagst!" Matthias Claudius
"Wer sich über Kritik ärgert, gibt zu, daß er sie verdient hat." Tacitus
  Mit Zitat antworten Zitat
alkan

Registriert seit: 8. Aug 2008
7 Beiträge
 
#5

Re: Problem beim Zugriff auf TObjectList aus Threads

  Alt 9. Okt 2008, 22:05
Zitat von Roachford:
Ein paar Gedanken von mir dazu:
Und dein Hauptfehler:

- du lässt den Thread sofort loslaufen, und das bevor der Constructor abgearbeitet ist und somit bevor die ObjectList Instanz gebildet wurde.
Vielen Dank Roachford für Deine Antwort! Es lag tatsächlich an diesem Problem, obwohl es mir nicht ganz einzuleuchten vermag.
Was Sirius geschrieben hat, kann ich zwar aufgrund meiner bescheidenen Kenntnisse nicht beurteilen. Aber irgendwie wäre es wirklich seltsam, wenn es so wäre, wie Du es geschrieben hast. Wenn ein Create(False) tatsächlich so unsicher ist, wozu kann man es denn überhaupt gebrauchen?
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#6

Re: Problem beim Zugriff auf TObjectList aus Threads

  Alt 10. Okt 2008, 01:02
Gibt es nicht eine TThreadList Klasse??
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Benutzerbild von Chemiker
Chemiker

Registriert seit: 14. Aug 2005
1.859 Beiträge
 
Delphi 11 Alexandria
 
#7

Re: Problem beim Zugriff auf TObjectList aus Threads

  Alt 10. Okt 2008, 01:13
Hallo Dezipaitor,

ja gibt es.

Bis bald Chemiker
wer gesund ist hat 1000 wünsche wer krank ist nur einen.
  Mit Zitat antworten Zitat
Roachford
(Gast)

n/a Beiträge
 
#8

Re: Problem beim Zugriff auf TObjectList aus Threads

  Alt 10. Okt 2008, 09:53
Zitat von alkan:
Es lag tatsächlich an diesem Problem, ...
Kann es nicht, da Sirius vollkommen Recht hat. Somit liegt der Fehler woanders - z.B. wenn du nach dem Konstruktor Eigenschaften zuweist, dann würde dies Problem wieder bestehen. Alle Zuweisungen innerhalb des Konstruktors sind aber sicher.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:41 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz