[Gelöst] Multithread-Exeption -- Multithread-Alternative ?!

Für Fragen von Einsteigern und Programmieranfängern...
mark332
Beiträge: 202
Registriert: Do 16. Mai 2013, 13:49
OS, Lazarus, FPC: Windows 10 H.P. (x64) / Ubuntu 14.04.X
CPU-Target: AMD Octacore 4.0GHz

Re: Multithread-Exeption [HELP] -- Multithread-Alternative ?

Beitrag von mark332 »

Socke hat geschrieben:
mark332 hat geschrieben:hmm... okay, das hat schonmal ein bisschen geholfen, jetzt würde mich nurnoch interessieren, ob es möglich ist mit Syncronize(@Bla) möglich ist, der Prozedur/Funktion, die aufgerufen wird, paramater mitzugeben.
Nein. Synchronize() hat allein den Zweck, eine Methode im Main-Thread auszuführen. Die Daten kannst du als Eigenschaften deines TThread-Objektes Verfügbar machen.
Ich habe das Ganze jetzt mal so versucht: (klappt leider immernoch nicht :( )

Code: Alles auswählen

 
procedure DownloadThread.ThreadFinish;
begin
Finish := true
end;
 
procedure DownloadThread.ShowDLStat();
begin
Form1.Memo_step.Lines.Add(LString)
end;
 
procedure DownloadThread.setDLCaption();
begin
Form1.StaticText_download.caption:=LString;
end;
 
procedure DownloadThread.setProgressBar();
begin
Form1.ProgressBar_download.position:=LInt;
end;
 
procedure DownloadThread.Execute;
var
  i: Integer;
  MaxCurSteps: Integer;
  Step: Integer;
  CurStep: Integer;
  captions: String;
  failes: Boolean;
  str: String;
 begin
 
for i:=0 to (MaxCurSteps-1) do
    begin
    LString := '';
    Synchronize(@ShowDLStat);
    if (i = 4) or (i = 6) then
       begin
       LString:='Downloading '+recs[i]+' || This will take a while! ||';
       Synchronize(@ShowDLStat);
       end
       else
       begin
       LString:='Downloading '+recs[i];
       Synchronize(@ShowDLStat);
    end;
 
CurStep:=i+1;
captions:= 'Installiere... : Schritt '+IntToStr(Step)+'/2 ('+IntToStr(CurStep)+'/'+IntToStr(MaxCurSteps)+')';
LString:= captions;
Synchronize(@setDLCaption);
 
LInt := CurStep;
Synchronize(@setProgressBar);
 
FTPDownload('source/'+recs[i],InstalDir+'\'+dest[i]);
LString:='Extracting '+dest[i];
Synchronize(@ShowDLStat);
 
CurStep:=i+1;
captions:= 'Installiere... : Schritt '+IntToStr(Step)+'/2 ('+IntToStr(CurStep)+'/'+IntToStr(MaxCurSteps)+')';
 
end;
Synchronize(@ThreadFinish)
 end; 
Was ich im Grunde ja nur benötige ist, das hinzufügen von Line im Memo-Feld, das ändern der caption eines Labels und das ändern der Position der Progressbar aus dem zweiten Thread heraus, gibt es also die möglichkeit, variablen des Hauptthreads aus einem nebenthread zu ändern ?

MfG mark332

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Multithread-Exeption [HELP] -- Multithread-Alternative ?

Beitrag von mschnell »

mark332 hat geschrieben:... werden die damit aufgerufenen prozeduren/funktionen, an das Ende von Thread gesetzt und und auch erst am Ende ausgeführt,
Ganz falsch .

- Mit Synchronize wird eine Methode im Mainthread ausgeführt, sobald dieser alle bisher beauftragten anderen Aktivitäten fertig hat. Der beauftragende Worker-Thread wartet so lange bis der Mainthread die Methode fertig bearbeitet hat. Das kann u.U,. "ewig" dauern, wenn der Mainthread gerade irgendetwas ganz anderes zu tun hat. Dann läuft der Worker-Thread normal weiter. Vorteil: man braucht sich über Korruption wegen gemeinsam benutzter Variablen keine Gedanken machen, da alles hintereinander abläuft

- Mit Queue und QueueAsyncCall wird eine Methode im Mainthread ausgeführt, sobald dieser alle bisher beauftragten anderen Aktivitäten fertig hat. Der beauftragende Worker-Thread läuft während dessen einfach normal weiter. Vorteil: Der Worker Thread wird nicht in seinen Aktivitäten gebremst. Nachteil: man muss sich über Korruption wegen gemeinsam benutzter Variablen in jedem Fall Gedanken machen, da alles parallel abläuft

- QueueAsyncCall kann zudem noch (einen Pointer auf) eine Daten-Struktur transportieren.

mark332 hat geschrieben: was ich brauche, ist allerdings, dass diese Prozedur/Funktion augenblicklich ausgeführt wird
Das geht nicht, Der Mainthread kann mit irgendwelchem Zeug beschäftigt sein. für "augenblicklich auszuführende" Aktionen sind Worker Threads da. die haben genau deswegen auch keine schneckenhafte GUI Anbindung.
mark332 hat geschrieben: ..., hat da jemannd eine Idee?
Das Konzept ist einfach falsch.

mark332 hat geschrieben: Was ich im Grunde ja nur benötige ist, das hinzufügen von Line im Memo-Feld
Ah, da ist der Wurm.

Du verwendest das Memo anscheinend als Datenspeicher. Das geht für schnelle Aktionen nicht, weil TMemo eine (zwangsläufig langsame) GUI Anbindung hat. Eigentlich ist TMemo zum Anzeigen gedacht. Da kommt es auf Geschwindigkeit nicht an.

Nimm also eine TStringlist zum schnellen Speichern Deiner Daten.
Dann machst Du ab ab und zu eine Kopie in eine andere TStringlist (damit später bei der Parallel-Verarbeitung nichts passieren kann) und dann machst Du entweder TThread.Queue() oder Application.QueueAsyncCall();
In der aufgerufenen Methode machst Du dann eine Kopie in das Memo.

Dadurch kann der Worker-Thread unbehelligt weiterschnurren.

-Michael

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Multithread-Exeption [HELP] -- Multithread-Alternative ?

Beitrag von Scotty »

Eine TStringList ist nicht threadsafe. Die Suchmaschine deiner Wahl liefert die einfache Erweiterung per CriticalSection.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Multithread-Exeption [HELP] -- Multithread-Alternative ?

Beitrag von mschnell »

Scotty hat geschrieben:Eine TStringList ist nicht threadsafe.
Braucht sie in diesem Fall auch nicht sein. "Threadsafe" braucht man nur, wenn auf ein Objekt gleichzeitig von zwei Threads zugegriffen werden soll.

Wie gesagt ist der Vorschlag im Thread die StringList Instanz in eine andere zu Kopieren (mit Assign). Das passiert komplett im Thread, braucht also keine Absicherung. Die zweite Liste wird nach dem Füllen vom Thread nicht mehr angepackt. Auch hier wird also keine Absicherung gebraucht.

Ich würde dann im Mainthread-Event die 2. StringList in das Memo kopieren (z.B. mit Memo1.Lines.Assign() und die 2. Stringlist dann mit FreeAndNil löschen.

Der Worker-Thread schaut dann z.B. jede Sekunde einmal nach, ob die 2. Liste nicht mehrt existiert ( if assigned() ...) (sie also vom Mainthread inzwischen ausgegeben worden ist) und kreiert und füllt sie dann neu.

-Michael

mark332
Beiträge: 202
Registriert: Do 16. Mai 2013, 13:49
OS, Lazarus, FPC: Windows 10 H.P. (x64) / Ubuntu 14.04.X
CPU-Target: AMD Octacore 4.0GHz

Re: Multithread-Exeption [HELP] -- Multithread-Alternative ?

Beitrag von mark332 »

mschnell hat geschrieben:
Scotty hat geschrieben:Eine TStringList ist nicht threadsafe.
Braucht sie in diesem Fall auch nicht sein. "Threadsafe" braucht man nur, wenn auf ein Objekt gleichzeitig von zwei Threads zugegriffen werden soll.

Wie gesagt ist der Vorschlag im Thread die StringList Instanz in eine andere zu Kopieren (mit AddStrings). Das passiert komplett im Thread, braucht also keine Absicherung. Die zweite Liste wird nach dem Füllen vom Thread nicht mehr angepackt. Auch hier wird also keine Absicherung gebraucht.

-Michael
wäre cool, wenn mir einer von euch ein Beispiel dazu schreiben würde, damit ich das ganze in 3 Monaten auch noch verstehe ;)

MfG mark332
------------------------------------------------------------
Warum gibt es hier eigentlich kein [SPOILER][/SPOILER] ?

mark332
Beiträge: 202
Registriert: Do 16. Mai 2013, 13:49
OS, Lazarus, FPC: Windows 10 H.P. (x64) / Ubuntu 14.04.X
CPU-Target: AMD Octacore 4.0GHz

Re: Multithread-Exeption [HELP] -- Multithread-Alternative ?

Beitrag von mark332 »

+: habe gerade festgestellt, dass der Thread auf diese Art funktioniert, also alle Dateien ohne Fehler heruntergeladen werden ?!?

Bis auf einen einzigen:

Code: Alles auswählen

List Index(12) Out of Bounds exeption
Der String(12) der StringList ist: 'ReadMe.txt' und die Datei wird auch vollständig heruntergeladen, der Fehler wird also am Ende vom Thread ausgelöst (!?!), hat da jemand eine Idee, woran das liegen könnte?


MfG
mark332


PS: Einen solchen Fehler hatte ich schon 2mal, diesen habe ich jedesmal behoben, indem ich an der "for"-Schleife das "to" Argument geändert habe...
------------------------------------------------------------
Warum gibt es hier eigentlich kein [SPOILER][/SPOILER] ?

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Multithread-Exeption [HELP] -- Multithread-Alternative ?

Beitrag von Socke »

mark332 hat geschrieben:PS: Einen solchen Fehler hatte ich schon 2mal, diesen habe ich jedesmal behoben, indem ich an der "for"-Schleife das "to" Argument geändert habe...
Bei TStringList gibt die Eigenschaft Count an, wie viele Einträge/Zeilen vorhanden sind. Der maximale Index, mit dem man darauf zugreifen darf, ist daher um eins geringer (der erste Eintrag hat den Index 0). Bei dir bedeutet der Fehler so viel wie: Es wird versucht auf den Index 12 zuzugreifen, der ist aber nicht definiert. Die Stringlist hat maximal 12 Einträge (mit den Indizes 0 bis 11).

Im Quelltext sieht das so aus:

Code: Alles auswählen

var
s: TStringList;
i: Integer;
begin
  for i := 0 to s.Count - 1 do
    writeln(s[i]);
end;
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

mark332
Beiträge: 202
Registriert: Do 16. Mai 2013, 13:49
OS, Lazarus, FPC: Windows 10 H.P. (x64) / Ubuntu 14.04.X
CPU-Target: AMD Octacore 4.0GHz

Re: Multithread-Exeption [HELP] -- Multithread-Alternative ?

Beitrag von mark332 »

Socke hat geschrieben:
mark332 hat geschrieben:PS: Einen solchen Fehler hatte ich schon 2mal, diesen habe ich jedesmal behoben, indem ich an der "for"-Schleife das "to" Argument geändert habe...
Bei TStringList gibt die Eigenschaft Count an, wie viele Einträge/Zeilen vorhanden sind. Der maximale Index, mit dem man darauf zugreifen darf, ist daher um eins geringer (der erste Eintrag hat den Index 0). Bei dir bedeutet der Fehler so viel wie: Es wird versucht auf den Index 12 zuzugreifen, der ist aber nicht definiert. Die Stringlist hat maximal 12 Einträge (mit den Indizes 0 bis 11).

Im Quelltext sieht das so aus:

Code: Alles auswählen

var
s: TStringList;
i: Integer;
begin
  for i := 0 to s.Count - 1 do
    writeln(s[i]);
end;

einen Versuch ist's wert
------------------------------------------------------------
Warum gibt es hier eigentlich kein [SPOILER][/SPOILER] ?

mark332
Beiträge: 202
Registriert: Do 16. Mai 2013, 13:49
OS, Lazarus, FPC: Windows 10 H.P. (x64) / Ubuntu 14.04.X
CPU-Target: AMD Octacore 4.0GHz

Re: Multithread-Exeption [HELP] -- Multithread-Alternative ?

Beitrag von mark332 »

mark332 hat geschrieben:
Socke hat geschrieben:
mark332 hat geschrieben:PS: Einen solchen Fehler hatte ich schon 2mal, diesen habe ich jedesmal behoben, indem ich an der "for"-Schleife das "to" Argument geändert habe...
Bei TStringList gibt die Eigenschaft Count an, wie viele Einträge/Zeilen vorhanden sind. Der maximale Index, mit dem man darauf zugreifen darf, ist daher um eins geringer (der erste Eintrag hat den Index 0). Bei dir bedeutet der Fehler so viel wie: Es wird versucht auf den Index 12 zuzugreifen, der ist aber nicht definiert. Die Stringlist hat maximal 12 Einträge (mit den Indizes 0 bis 11).

Im Quelltext sieht das so aus:

Code: Alles auswählen

var
s: TStringList;
i: Integer;
begin
  for i := 0 to s.Count - 1 do
    writeln(s[i]);
end;

einen Versuch ist's wert
Okay, damit wäre das Problem gelöst :D *freu* :D

Danke an alle, die mir geantwortet haben ;)

MfG mark332
------------------------------------------------------------
Warum gibt es hier eigentlich kein [SPOILER][/SPOILER] ?

Antworten