[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

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

Beitrag von mark332 »

Moin Leute ;) (für die, die mich kennen: Ja ich bins schonwieder und: Selbes Programm ;) ),

ich schreibe derzeit ein Programm, das dem User ein paar Dateien aus einem FPT-Server herunterladen soll, damit mein Programm aber nicht einfriert ("Keine Rückmeldung") wollte ich das ganze in einen Zweiten Thread verpacken, das funzt auch bei der ersten (manchmal auch bei der zweiten) Datei ganz gut, dann löst mein Programm aber eine Exeption aus, mit der ich leider nicht umzugehen weiß :oops: , ich hoffe ihr könnt mir helfen.

Ebenfalls möchte ich wissen, ob es dafür auch eine alternative/einfachere Methode gibt :oops: , die ich noch nicht gefunden habe

Die Exeption-Ausgabe:

Code: Alles auswählen

 
Projekt Minecraft_Multilauncher_Setup hat
Ecxeption-Klasse >>External: SIGSEGV<< ausgelöst.
 
Bei Adresse 73726573
 

Thread-Execute-Code und von ihm genutzte prozeduren:

Code: Alles auswählen

 
procedure TForm1.ShowDLStat(LCapt: String);
begin
Form1.Memo_step.Lines.Add(LCapt)
end;
 
procedure TForm1.setDLCaption(LCapt: String);
begin
Form1.StaticText_download.caption:=LCapt;
end;
 
procedure TForm1.setProgressBar(LStep: Integer);
begin
Form1.ProgressBar_download.position:=LStep;
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
 
    Form1.ShowDLStat('');
    if (i = 4) or (i = 6) then
       begin
       Form1.ShowDLStat('Downloading '+recs[i]+' || This will take a while! ||');
       end
       else
       begin
       Form1.ShowDLStat('Downloading '+recs[i]);
    end;
 
CurStep:=i+1;
captions:= 'Installiere... : Schritt '+IntToStr(Step)+'/2 ('+IntToStr(CurStep)+'/'+IntToStr(MaxCurSteps)+')';
Form1.setDLCaption(captions);
Form1.setProgressBar(CurStep);
 
FTPDownload('source/'+recs[i],InstalDir+'\'+dest[i]);
Form1.ShowDLStat('Extracting '+dest[i]);
// Sleep(50);
captions:= 'Installiere... : Schritt '+IntToStr(Step)+'/2 ('+IntToStr(CurStep)+'/'+IntToStr(MaxCurSteps)+')';
end;
 end; 
Der Code der Procedure, die das Ganze ausführt:

Code: Alles auswählen

 
procedure TForm1.Button_performInstalClick(Sender: TObject);
{  dirs: TStringList;
  recs: TStringList;
  dest: TStringList; }
var
  MyDownloadThread : DownloadThread;
  MaxCurSteps: Integer;
  Step: Integer;
  CurStep: Integer;
  captions: String;
  failes: Boolean;
  str: String;
  i: Integer;
 
 
  File1,File2,File3: TextFile;
//----------------------------//
begin
 Button_prev.Enabled:=false;
 application.ProcessMessages;
 Screen.Cursor:=crHourGlass;
 Sleep(500);
dirs:= TStringList.create;
recs:= TStringList.create;
dest:= TStringList.create;
Memo_step.Lines.Add('Reading relevant Files...');
 
 
Sleep(800);
 
// Files auslesen
recs.LoadFromFile('resource.txt');
recs.TextLineBreakStyle:=tlbsLF;
 
dirs.LoadFromFile('dirs.txt');
dirs.TextLineBreakStyle:=tlbsLF;
 
dest.LoadFromFile('destination.txt');
dest.TextLineBreakStyle:=tlbsLF;
 
StaticText_download.visible:=true;
 
MaxCurSteps:= dirs.Count;
ProgressBar_download.Max:=MaxCurSteps-1;
Step:=1;
CreateDir(InstalDir);
for i:=0 to (dirs.Count-1) do
begin
CurStep:=i+1;
Memo_step.Lines.Add('Creating Directory: '+dirs[i]);
CreateDir(InstalDir+'\'+dirs[i]);
Sleep(400);
captions:= 'Installiere... : Schritt '+IntToStr(Step)+'/2 ('+IntToStr(CurStep)+'/'+IntToStr(MaxCurSteps)+')';
StaticText_download.caption:=captions;
ProgressBar_download.position:=CurStep;
end;
 
Sleep(500);
MaxCurSteps:= dest.Count;
Step:=2;
ProgressBar_download.Max:=MaxCurSteps;
if FTPLogin(FTPUser,FTPPass,'mark332.bplaced.net','21') = true then
 begin
 
 MyDownloadThread := DownloadThread.Create(false);
 
FTPLogout;
failes:=false;
end
 
else
begin
ShowMessage('Login Error occured! Please contact mark332/Life4YourGames !');
failes:=true;
end;
Screen.Cursor:=crDefault;
if (failes=true) then
 begin
 ShowMessage('Es ist ein Fehler aufgetreten, setze Installation zurück!');
 Sleep(500);
 DeleteDirectory(InstalDir, true);
 rmDir(InstalDir);
 
 if FileExists('resource.txt') then
  begin
  DeleteFile('resource.txt')
  end;
if FileExists('destination.txt') then
 begin
 DeleteFile('destination.txt')
 end;
if FileExists('dirs.txt') then
 begin
 DeleteFile('dirs.txt')
 end;
 Application.Terminate;
 end;
 
 
if not (failes=true) then
 begin
 ShowMessage('Erfolgreich installiert!');
 Button_prev.Enabled:=false;
 x:=x+1;
 LockExit:=false;
end;
end; 

Wenn ihr nicht durchblickt, weil es unordentlich ist, sagt bescheid :). Ich werde es dann wieder ohne Multithreading versuchen ;D

MfG mark332
Zuletzt geändert von mark332 am Sa 6. Jul 2013, 19:30, insgesamt 1-mal geändert.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

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

Beitrag von mse »

DownloadThread.Execute() darf nicht auf GUI Elemente des mainthread zugreifen.

Code: Alles auswählen

 
procedure TForm1.ShowDLStat(LCapt: String);
begin
Form1.Memo_step.Lines.Add(LCapt)
end;
z.B. triggert ein Neuzeichnen des Form1.Memo, dadurch kann es vorkommen, dass der mainthread mit dem Neuzeichnen beschäftigt ist, auf die Lines list zugreift, vom downloadthread unterbrochen wird, der die Lines list verändert, dann kracht es. Um dies zu vermeiden hat MSEgui application.lock()/unlock, ich weiss nicht, wie die Lazarus-Entsprechung heisst. Noch besser wäre es, die GUI Funktionen komplett im mainthread abzuarbeiten und die anzuzeigenden Informationen z.B. mittels message queue vom download thread in den mainthread zu übertragen.

Martin

Benutzeravatar
theo
Beiträge: 10873
Registriert: Mo 11. Sep 2006, 19:01

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

Beitrag von theo »

RTFM, wenn du auf den Main Thread zugreifen musst, kannst du Synchronize verwenden:

http://wiki.lazarus.freepascal.org/Mult ... se_TThread

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 »

hmm... okay, ich werd' morgen mal versuchen, damit etwas anzufangen...

Danke für die Antworten ;)
------------------------------------------------------------
Warum gibt es hier eigentlich kein [SPOILER][/SPOILER] ?

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 »

Macht Du etwa im "Worker"-Thread irgendetwas auf der grafischen Oberfläche ?????

Das ist strikt verboten !!!!

Du kannst Application.QueuAsyncCall() verwenden um vom Thread aus ein Event im Mainthread zu schmeißen, in dem Du dann z.B. Mitteilungen an den Benutzer machen oder einen Fortschrittsbalken managen kannst.

("TThgread.Queueu" und "TThread.Synchronize" sind nicht so geschickt, weil Du keine Daten mitgeben kannst, außerdem muss bei Synchronize fer Thread noch warten, bis der Mainthread das Event bearbeitet hat, das kann - muss aber nicht - sinnvoll sein.)

-Michael

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 »

theo hat geschrieben:RTFM, wenn du auf den Main Thread zugreifen musst, kannst du Synchronize verwenden:
Stimmt. (Je nach Anwendung ist aber TThread.Queue oder Application.QueueAsyncCall besser.)

-Michael

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 »

mschnell hat geschrieben:
theo hat geschrieben:RTFM, wenn du auf den Main Thread zugreifen musst, kannst du Synchronize verwenden:
Stimmt. (Je nach Anwendung ist aber TThread.Queue oder Application.QueueAsyncCall besser.)
Ist TApplication.QueueAsyncCall überhaupt threadsicher?! Ich wäre davon ausgegangen, man müsste diese Methode innerhalb des Main-Threads aufrufen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

g3sh
Beiträge: 21
Registriert: Mi 3. Jul 2013, 10:04

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

Beitrag von g3sh »

Socke hat geschrieben:Ist TApplication.QueueAsyncCall überhaupt threadsicher?!
Laut Beschreibung ist sie das: http://lazarus-ccr.sourceforge.net/docs ... ccall.html

Aber hier meint auch jemand was anderes: http://lists.lazarus.freepascal.org/pip ... 48547.html

MfG

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 »

Hmm... okay die Sache mit Application.QueuAsyncCall() hört sich gut an, leider verstehe ich die Nutzung, trotz googeln ;) , leider nicht... :oops:
Würde mich freuen, wenn sich einer die Mühe macht, mir das zu erklären :D


MfG
mark332

Benutzeravatar
theo
Beiträge: 10873
Registriert: Mo 11. Sep 2006, 19:01

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

Beitrag von theo »

Nimm Synchronize, das ist die empfohlene Methode und das Bsp. ist hier:
http://wiki.lazarus.freepascal.org/Mult ... se_TThread

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 »

theo hat geschrieben:Nimm Synchronize, das ist die empfohlene Methode und das Bsp. ist hier:
http://wiki.lazarus.freepascal.org/Mult ... se_TThread
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.

Z.B.:

Code: Alles auswählen

 
procedure MyThread.setCaption(Lcaption: String);
begin
Form1.caption:= Lcaption;
end;
 
so aufzurufen

Code: Alles auswählen

 
Synchronize(@setCaption("Test") ); //[Edit:]  <-- Diese Methode hab' ich schon versucht :/ ohne Erfolg
 
MfG mark332


PS: Ob mein Problem gelöst ist, weiß ich erst, wenn ich das theoretische fertig und verstanden habe, vorher brauche ich es nicht zu testen ;)

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 »

theo hat geschrieben:Nimm Synchronize, das ist die empfohlene Methode
Nur bei Delphi ist das "empfohlen". Lazarus kann da mehr.

Bei Delphi gibt es inzwischen auch TThread.Queue(). Allerdings gibt es bei Delphi Application.QueueAsncCall() nicht.

-Michael

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: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.
Nö. Deshalb QueueAsyncCall().

Als Behelf kann man natürlich irgendetwas irgendwo speichern und dann in der aufgerufenen Methode verwenden.

-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:
mark332 hat geschrieben: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.
Nö. Deshalb QueueAsyncCall().

Als Behelf kann man natürlich irgendetwas irgendwo speichern und dann in der aufgerufenen Methode verwenden.

-Michael
Soweit ich das lesen konnte: ( http://wiki.freepascal.org/Asynchronous_Calls ) werden die damit aufgerufenen prozeduren/funktionen, an das Ende von Thread gesetzt und und auch erst am Ende ausgeführt, was ich brauche, ist allerdings, dass diese Prozedur/Funktion augenblicklich ausgeführt wird, sowas wie Syncronize(@Bla) mit Parameterfunktion..., hat da jemannd eine Idee?


MfG mark332

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: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.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten