Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Result als mehrdimensoiertes array im Thread (https://www.delphipraxis.net/191332-result-als-mehrdimensoiertes-array-im-thread.html)

alfold 3. Jan 2017 15:39

Delphi-Version: 7

Result als mehrdimensoiertes array im Thread
 
Hi, zur Zeit hänge ich an dieses Problem.

Ich bekomme im Mainthread immer ein leeres array zurück!
Im thread selbst wird es gefüllt.

Nun weiß ich nicht mehr weiter!

Delphi-Quellcode:
...
.....

type
  tarray = array[1..4] of array of Boolean;
....
....
private
  fisfilea: tarray;/
  .....
  .....
  function Getfile: tarray;


public
   property isfile: tarray read Getfile;
....
....


procedure TLwThread.Execute;
var
  i, x: Integer;
begin
    try
        while not Terminated do
        begin

            if (WaitForSingleObject(FEvent, INFINITE) = WAIT_OBJECT_0) and not Terminated then
            begin
               for i:= 1 to 4 do
               begin
                   if FileList[i].Count > 0 then
                    begin
                        for x:= 0 to FileList[i].Count -1 do
                        begin
                            if FileExists(FileList[i].Strings[x]) then
                               fisfilea[i][x]:= True
                            else
                               fisfilea[i][x]:= False;

                         end;
                     end;

               end;
              // Getfile;
            end;
            Sleep(1);
        end;

    except
        Finished;
    end;
.....
.....
.....

function TLwThread.Getfile: tarray;
var
  i, x: Integer;
begin
    for i:= 1 to 4 do
    begin
       SetLength(Result[i], Length(fisfilea[i]));
       //for x:= 0 to high(Result[i]) do
       begin
           Result[i]:= Copy(fisfilea[i]);


       end;
    end;
    // if Length(fisfilea[1]) > 0 then
   // Result:=fisfilea;
end;
Dabei hab ich festgestellt,
das "wahrscheinlich" das array in der function Getfile leer ist, obwohl es in execute gefühlt wird.

Allerdings weiß ich auch nicht so recht wie die Übergabe erfolgt!

wer kann da helfen

Gruß

p80286 3. Jan 2017 16:45

AW: Result als mehrdimensoiertes array im Thread
 
Zum einen fehlt mir das setlength im .Execute zum anderen würde ich einen Pointer übergeben. Diesen Kopierschritt halte ich für viel zu fehleranfällig.

Gruß
k-H

samso 3. Jan 2017 16:57

AW: Result als mehrdimensoiertes array im Thread
 
Wie synchronisierst Du denn den Mainthread mit dem nebenläufigen Thread? Der Mainthread sollte ja erst dann auf das Ergebnis Deines Threads zugreifen, wenn dieser auch wirklich durch die Excute-procedure durchgelaufen ist. Falls der Mainthread vorher zugreift, ist das Ergebnis natürlich leer.

alfold 3. Jan 2017 17:13

AW: Result als mehrdimensoiertes array im Thread
 
Zitat:

Zitat von p80286 (Beitrag 1357965)
Zum einen fehlt mir das setlength im .Execute ...
k-H

befindet sich im setter.
Pointer mh? :gruebel:

Zitat:

Zitat von samso (Beitrag 1357973)
Wie synchronisierst Du denn den Mainthread mit dem nebenläufigen Thread?.

Der Thread läuft selbstständig um den Mainthread nicht abhängig zu machen. Der Thread erhält lediglich die Listen vom Mainthread.

Hatte zwar was gefunden im Inet, bezog sich aber auf ein eindimensionales Array, deshalb noch die Fragmente in Getfile!

Gruß

himitsu 3. Jan 2017 18:04

AW: Result als mehrdimensoiertes array im Thread
 
Gleichzeitige Zugriffe auf eine Variable aus zwei Threads.

Was sollte man da wohl drumrum machen? :roll:

alfold 3. Jan 2017 18:20

AW: Result als mehrdimensoiertes array im Thread
 
Zitat:

Zitat von himitsu (Beitrag 1357982)
Gleichzeitige Zugriffe auf eine Variable aus zwei Threads.

Was sollte man da wohl drumrum machen? :roll:

Sitze schon seit tagen dran! Neu geschrieben x mal geändert usw.
Wo hab ich was übersehen:?::gruebel:

Gruß

himitsu 3. Jan 2017 18:38

AW: Result als mehrdimensoiertes array im Thread
 
Hier im Forum suchenCriticalSection
Delphi-Referenz durchsuchenSyncObjs
Delphi-Referenz durchsuchenTCriticalSection
MSDN-Library durchsuchenEnterCriticalSection
Delphi-Referenz durchsuchenTMultiReadExclusiveWriteSynchronizer
...

alfold 3. Jan 2017 19:50

AW: Result als mehrdimensoiertes array im Thread
 
Zitat:

Zitat von himitsu (Beitrag 1357982)
Was sollte man da wohl drumrum machen? :roll:

Ja kommt noch im Original:wink:
Aber es geht erst mal um den Getter!

Gruß

alfold 4. Jan 2017 09:24

AW: Result als mehrdimensoiertes array im Thread
 
Liste der Anhänge anzeigen (Anzahl: 1)
Jetzt steh ich richtig aufn Schlauch!!!!!
Beim Check des ganzen, hab ich festgestellt das im execute nur kurz
Werte vorhanden sind!?
Dann kommt es zu mehrerern durchläufen wo keine Werte da sind. irgendwann sind werte wieder da,
aber auch nur kurz. Danach wieder weg!
Der Setter wird vom Mainthread nur einmal aufgerufen, wenn dort die Filelist gefühlt wird. ansonsten nur wenn sich was in der dortigen Filelist was ändert.

Und dies hat bestimmt nix mit fehlender Sicherheit zu tun.
CriticalSection, usw.

Irgendwo hab ich einen Fehler!
Ich hänge mal die Pas mit an.
Gruß

stahli 4. Jan 2017 09:56

AW: Result als mehrdimensoiertes array im Thread
 
Den Anhang habe ich mir jetzt noch nicht angesehen, aber am gestrigen Schnipsel fand ich eigenartig, dass im Getter der Speicher reserviert wird und der Thread selbst nur auf das private Array zugreift.
Vielleicht liegt da ja das Problem.

PS: Reserviert SetLength evtl. sogar neuen Speicher, wenn sich die bisherige Größe dadurch gar nicht ändert? Bin hier unsicher.

alfold 4. Jan 2017 10:50

AW: Result als mehrdimensoiertes array im Thread
 
Mh, Result muss ja irgendwann mal die Größe bekommen!
also muss ich im getter Result bei der Abfrage vom Meinthread setzen.
Oder ich könnte Result vorher abfragen ob es schon gesetzt ist. Ob das geht, hab ich noch nicht getestet?

Ursache ist aber EXECUTE dort sind die daten nicht fix. Demzufolge auch nicht im Getter. Wie sich herraustellte. Warum keine Ahnung!
Bin noch am suchen:gruebel:

Den getter hab ich jetz erstmal ganz entfernt!
Gruß

Mavarik 4. Jan 2017 11:26

AW: Result als mehrdimensoiertes array im Thread
 
Dein Getter der die Werte abfragt kümmert sich nicht darum ob der Thread noch läuft...

Vielleicht leitest Du mal Deine Klasse von meinem mini-Threadhelper ab...

Mavarik...

stahli 4. Jan 2017 11:27

AW: Result als mehrdimensoiertes array im Thread
 
Übersichtlicher wäre es sicher, das Array im Mainthread zu erstellen und dem nebenläufigen Thread zu übergeben (
Delphi-Quellcode:
MyThread := TMyThread.Create(MyArray)
)

Den Zugriff musst Du aber auf jeden Fall absichern bzw. synchronisieren.

alfold 4. Jan 2017 11:37

AW: Result als mehrdimensoiertes array im Thread
 
Danke für alles!
Fehler gefunden. Ich hab im Mainthread ausversehen den Thread 2x erstellt. Deswegen auch immer execute der Fehler daten da/nicht da.:oops:

Das Absichern kommt jetzt!
Synchronisieren mit den Mainthread? Nö
Hat seine Grund.

THX für Eure Bemühngen

Gruß Alfold
und damit keine offene Frage mehr.

Fritzew 4. Jan 2017 12:16

AW: Result als mehrdimensoiertes array im Thread
 
Also ich würde das in etwa so umsetzen:

Delphi-Quellcode:
unit newLwThread;

interface

uses
   Windows,
   Classes,
   SysUtils,
   Syncobjs;

type

   tarray = array [1 .. 4] of array of Boolean;

   TnewLwThread = class(TThread)
   private
      FEvent: TEvent;
      fFileList: array [1 .. 4] of TStringList;
      fisfilea: tarray; // array[1..4] of array of Boolean;
      fIsFileIndex: Integer;
      fIsListIndex: Integer;

      fLock: array [1 .. 4] of Tcriticalsection;

      procedure setFileList(index: Integer; const Value: TStringList);
      function Getfile: tarray;

   protected
      procedure Execute; override;

   public
      constructor Create;
      destructor Destroy; override;
      procedure ContinueWork;
      procedure Terminate;

      property Titel[index: Integer]: TStringList write setFileList;
      property isfile: tarray read Getfile;
   end;

implementation

{ TnewLwThread }

constructor TnewLwThread.Create;
var
   i: Integer;
begin
   inherited Create(true);
   FEvent := TEvent.Create(nil, false, false, '');
   for i := 1 to 4 do
      begin
         fFileList[i] := TStringList.Create;
         fLock[i] := Tcriticalsection.Create;
      end;
   FreeonTerminate := false;

end;

destructor TnewLwThread.Destroy;
var
   i: Integer;
begin
   ContinueWork;
   if not Terminated then
      begin
         Terminate;
         ContinueWork;
         WaitFor;
      end;
   for i := 1 to 4 do
      begin
         fFileList[i].Free;
         fLock[i].Free;
         SetLength(fisfilea[i], 0);
      end;
   FEvent.Free;
   inherited;
end;

procedure TnewLwThread.ContinueWork;
begin
   (* Event auf Signaled setzen *)
   FEvent.SetEvent;
end;

procedure TnewLwThread.setFileList(index: Integer; const Value: TStringList);
begin
   if index in [1 .. 4] then
      begin
         fLock[index].Enter;
         fFileList[index].Clear;
         fFileList[index].Assign(Value);
         SetLength(fisfilea[index], fFileList[index].Count);
         fLock[index].Leave;
      end;
end;

procedure TnewLwThread.Execute;
var
   i, x: Integer;
begin
   while not Terminated do
      begin
         if (FEvent.WaitFor(INFINITE) = wrSignaled) and not Terminated then
            begin
               // checkfile;
               for i := 1 to 4 do
                  begin
                     fLock[i].Enter;
                     try
                        if fFileList[i].Count > 0 then
                           begin
                              for x := 0 to fFileList[i].Count - 1 do
                                 begin
                                    if FileExists(fFileList[i].Strings[x]) then
                                       if not fisfilea[i][x] then
                                          fisfilea[i][x] := true
                                       else if fisfilea[i][x] then
                                          fisfilea[i][x] := false;

                                 end;
                           end;
                        // getfile;
                     finally
                        fLock[i].Leave;
                     end;
                  end;

            end;
      end;
end;

procedure TnewLwThread.Terminate;
begin
   inherited Terminate;
   FEvent.SetEvent;
end;

function TnewLwThread.Getfile: tarray;
var
   i, j: Integer;
begin
   for i := 1 to 4 do
      begin
         fLock[i].Enter;
         try
            SetLength(result[i], length(fisfilea[i]));
            for j := 0 to length(fisfilea[i]) - 1 do
               result[i, j] := fisfilea[i, j];
         finally
            fLock[i].Leave;
         end;
      end;
end;

end.

p80286 4. Jan 2017 12:33

AW: Result als mehrdimensoiertes array im Thread
 
Zitat:

Zitat von alfold (Beitrag 1358034)
Synchronisieren mit den Mainthread? Nö
Hat seine Grund.

Synchronisieren bedeutet nicht irgendeine Funktion aufzurufen, sondern sicher zu stellen, daß nicht zwei Threads gleichzeitig auf ein und den selben Speicherbereich zugreifen.

sollte sich das "nö" hierauf beziehen solltest Du u.U. dein Hobby wechseln.

Gruß
K-H

himitsu 4. Jan 2017 13:17

AW: Result als mehrdimensoiertes array im Thread
 
Zitat:

Zitat von stahli (Beitrag 1358024)
PS: Reserviert SetLength evtl. sogar neuen Speicher, wenn sich die bisherige Größe dadurch gar nicht ändert? Bin hier unsicher.

SetLenght sorgt für ein UniqueArray. Wenn also aktuell mehrere Variablen auf dieses Array zeigen, dann legt SetLength eine neue Kopie an.

alfold 4. Jan 2017 17:38

AW: Result als mehrdimensoiertes array im Thread
 
Zitat:

Zitat von p80286 (Beitrag 1358042)
Zitat:

Zitat von alfold (Beitrag 1358034)
Synchronisieren mit den Mainthread? Nö
Hat seine Grund.

Synchronisieren bedeutet nicht irgendeine Funktion aufzurufen .....
sollte sich das "nö" hierauf beziehen solltest Du u.U. dein Hobby wechseln.

Gruß
K-H

Sorry ich dachte an synchronize mit den Mainthread:?
alles andere kommt jetzt dazu!

der Getter sieht jetzt so aus
Delphi-Quellcode:
function TLwThread.Getfile: tarray;
var
  i: Integer;
begin
    LwCS.Enter;
    try
       for i:= 1 to 4 do
       begin
             Result[i]:= Copy(fisfilea[i]);
       end;
    finally
      LwCS.Leave;
   end;
end;
@Fritzew
Macht das sinn für jedes Array ein CriticalSection?
Es wird eh einmal gelesen oder geschrieben? Zwischen durch darf kein anderer ran.

Gruß alfold

Fritzew 4. Jan 2017 19:31

AW: Result als mehrdimensoiertes array im Thread
 
Zitat:

Macht das sinn für jedes Array ein CriticalSection?
Es wird eh einmal gelesen oder geschrieben? Zwischen durch darf kein anderer ran.
Wie stellst Du sicher das keiner ran will?
Das war einfach auf die Schnelle um das Prinzip darzustellen.

Sperren sollten immer so kurz wie möglich sein, das war mit den Stringlisten das kürzeste:-D


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:03 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