Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Exception bei Thread-Verwendung (https://www.delphipraxis.net/94007-exception-bei-thread-verwendung.html)

ManuMF 14. Jun 2007 16:06


Exception bei Thread-Verwendung
 
Hallo,

da der IdHTTP mein Programm bei "normaler" Verwendung einfriert, möchte ich dafür einen Thread verwenden.
Da ich mich nicht so gut damit auskenne, habe ich die Komponente TIdThreadComponent genommen. Wenn ich jetzt aber mein Programm beende, nachdem der Thread mal gestartet wurde, kommt folgende Exception:
Code:
---------------------------
Anwendungsfehler
---------------------------
Exception EOSError in Modul UploadTool.exe bei 0000E096.

Systemfehler. Code: 1400.

Ungültiges Fensterhandle.

---------------------------
OK  
---------------------------
woran könnte das liegen? Wenn ich die Prozedur, die im Thread aufgerufen wird, normal aufrufe, ist der Fehler verschwunden.

Danke,
ManuMF

jfheins 14. Jun 2007 16:08

Re: Exception bei Thread-Verwendung
 
Ist TIdAntiFreeze nichts für dich?

ManuMF 14. Jun 2007 16:13

Re: Exception bei Thread-Verwendung
 
Schon, wenn es was bringen würde...

Wenn man mehr machen muss, als es bloß aufs Formular zu klatschen, bin ich noch nicht dahintergekommen ;-)

Application.ProcessMessages im IdHTTP.onWork läuft zwar, aber das kommt nur so einmal pro Sekunde.

jfheins 14. Jun 2007 23:11

Re: Exception bei Thread-Verwendung
 
Du musste es noch irgendwie auf activ stellen, und dem http sagen, er soll es benutzten - wenn ich mich recht erinnere ;)

ManuMF 15. Jun 2007 12:00

Re: Exception bei Thread-Verwendung
 
Ersteres war eine meiner ersten Aktionen nach dem Platzieren auf dem formular. Letzteres, also wie ich das mit dem IdHTTP verbinde, habe ich aber nicht rausgefunden. Auch die Indy-Hilfe war nicht hilfreich. :(

alzaimar 15. Jun 2007 12:58

Re: Exception bei Thread-Verwendung
 
Vielleicht solltest Du die HTTP-Komponente in einen Thread auslagern...

ManuMF 15. Jun 2007 13:40

Re: Exception bei Thread-Verwendung
 
Zitat:

Zitat von alzaimar
Vielleicht solltest Du die HTTP-Komponente in einen Thread auslagern...

Was genau? Das Erstellen etc. der Komponente?

alzaimar 15. Jun 2007 14:45

Re: Exception bei Thread-Verwendung
 
Nee, die gesamte Kommunikation. Also, so (ohne die Komponente zu kennen)

Delphi-Quellcode:
Procedure TMyThread.Execute;
Var
  cHttp : THTTPClient;

Begin
  cHtttp := THTTPClient.Create (Nil);
  Try
    SetupCommunicationParameter (cHttp);
    cHttp.SendRequest;
    cHttp.ReceiveAnswer;
  Finally
    cHtt.Free;
  End
End;
Natürlich ist das nur Pseudocode

ManuMF 15. Jun 2007 16:56

Re: Exception bei Thread-Verwendung
 
Momentan habe ich die Komponente auf dem Formular sitzen.
Im Thread wird neben der Vorbereitung (laden der Datei in einen Stream, anzeigen des Dateinamens etc.) nur
Delphi-Quellcode:
IdHTTP.Post(Stream, URL);
ausgeführt (mehr braucht die Kompo nicht). Kann es da helfen, das Create & Co. mit in den Thread zu nehmen?

C.Schoch 15. Jun 2007 17:22

Re: Exception bei Thread-Verwendung
 
Hi,
Du solltest die Komponente nach Möglichkeit dynamisch innerhalb des Threads erstellen.
Oder du realisierst sämtliche Zugriffe auf die Komponente per Syncronize.

Ersteres ist IMO zu bevorzugen.

ManuMF 15. Jun 2007 17:30

Re: Exception bei Thread-Verwendung
 
Jetzt wollte ich das gerade umsetzen, da bin ich an ein weiteres Problem gestoßen: Ich muss auch aus anderen Prozeduren auf den IdHTTP zugreifen, etwa um ihn per Buttonclick zu stoppen. Das geht also leider nicht :(

alzaimar 15. Jun 2007 17:43

Re: Exception bei Thread-Verwendung
 
Natürlich geht das. Dazu musst du nur den Zugriff (threadsicher!) auf die HTTP-Komponente über den Thread implementieren.

ManuMF 15. Jun 2007 17:51

Re: Exception bei Thread-Verwendung
 
Berühmte Frage ;-) : Wie?

C.Schoch 16. Jun 2007 12:14

Re: Exception bei Thread-Verwendung
 
Hi,
Schon mal was von Hier im Forum suchenCritical Section gehört?
Oder du benutzt einen Flag und lässt den Thread die Arbeit tun.

ManuMF 16. Jun 2007 13:31

Re: Exception bei Thread-Verwendung
 
bisher noch nicht, hab grad mal geschaut... uff, das ist ein sehr umfangreiches Thema.

Das mit CriticalSection hab ich nicht wirklich verstanden.
Dafür habe ich stattdessen die Komponente (IdThreadComponent) entfernt und den Thread selbst erzeugt. Wenn ich, wie hier gelesen, das ganze synchronisiert mache, gestaltet sich der Ablauf so, als ob es gar keinen Thread gäbe (Programm reagiert nicht oder selten). Wenn ich den eigenen Thread unsynchronisiert laufen lasse, reagiert das Programm problemlos: Die Progressbars erden aktualisiert, Klicks angenommen. Nur am Ende wieder die Exception mit dem Handle :(

Das Problem bei der Sache ist, dass die Progressbars etc. im onWork des IdHTTP aktualisiert werden, ich kann also nicht einfach die ganze Komponente in denThread verschieben.

C.Schoch 16. Jun 2007 14:16

Re: Exception bei Thread-Verwendung
 
Versuch mal die Komponente Dynamisch im Thread zu erzeugen, zunächst mal ohne Progress usw. wenn das soweit geht kannst dun nach und nach die Visualisierung einbauen.

Was das hängen betrifft, wenn du z.B: IDHttp.Get syncronisierst kannst du dir den Thread auch gleich schenken.

Zeig mal ein bischen relevanten Code

ManuMF 16. Jun 2007 14:31

Re: Exception bei Thread-Verwendung
 
Hmm also wenn ich die Progressbars ausbaue, dann können sie nicht mehr stocken, und das Problem ist natürlich gelöst ;)

Wie oben geschrieben, die einzige Zeile Code, sie aber eben das ganze Prog aufhält, ist IdHTTP.Post. Die Aktualisierung mache ich im onWork, deshalb wäre die dynamische Erzeugung eigentlich nutzlos, da der Zugriff auf die VCL ja bleibt. Übrigens wäre auch eine Aktualisierung per Timer nutzlos, da das Timer-Event nicht wie eingestellt kommt, sondern nur, wenn onWork ausgeführt wird und darin ProcessMessages steht.

Wie kann ich denn Post synchronisieren? Bzw. durch das Synchronisieren hängt alles erst ja.

DGL-luke 16. Jun 2007 14:37

Re: Exception bei Thread-Verwendung
 
Hallo,

synchronisiere nicht post.

verarbeite im thread das OnWork-Event und Synchronisiere dann ein Event, das du nach außen reichst.

ManuMF 16. Jun 2007 14:38

Re: Exception bei Thread-Verwendung
 
Zitat:

Zitat von DGL-luke
verarbeite im thread das OnWork-Event

wie das? bzw. wie weiß ich, wann ich das synchronisierte Event ausführen soll?

C.Schoch 17. Jun 2007 03:04

Re: Exception bei Thread-Verwendung
 
Ich mach mal ein Pseudocode Beispiel.

Delphi-Quellcode:
procedure MyOnWorkEvent(...);
begin
...
Syncronize(MyGUIUpdate);
...
end;

procedure MyGUIUpdate;
begin
...
Progressbar.Position := MyProgress;
...
end;
Ich hoffe jetzt wird es klar was wir meine (ich hoffe DGL-Luke hat das auch so ähnlich gemeint)

ManuMF 17. Jun 2007 10:15

Re: Exception bei Thread-Verwendung
 
Jetzt hab ichs verstanden :-D

OK, dann probiere ich es mal so.
Dann muss ich nur noch ein wenig umschreiben, da vor dem Post noch die Bars auf 0 gestellt werden etc., das muss dann wohl auch noch in eine synchronisierte Prozedur... oder kann ich quasi im Thread einen Bereich als synchronisiert bestimmen? Ach so, und kann ich im Thread auf globale Variablen zugreifen?

[Edit]
Stopp, das ganze funktioniert nicht. Ich muss per ButtonClick das IdHTTP stoppen können (.disconnect). Das geht aber natürlich nicht, wenn ich es dynamisch im Thread erstelle. :wall:
[/edit]

alzaimar 18. Jun 2007 07:52

Re: Exception bei Thread-Verwendung
 
Zitat:

Zitat von ManuMF
[Edit]
Stopp, das ganze funktioniert nicht. Ich muss per ButtonClick das IdHTTP stoppen können (.disconnect). Das geht aber natürlich nicht, wenn ich es dynamisch im Thread erstelle. :wall:
[/edit]

Doch. Du musst doch nur das 'Stopp' als Methode im Thread bereitstellen.

ManuMF 18. Jun 2007 07:58

Re: Exception bei Thread-Verwendung
 
Also z.B. MyThread.StopUpload und das im ButtonClick aufrufen? :gruebel:

alzaimar 18. Jun 2007 08:02

Re: Exception bei Thread-Verwendung
 
Jupp. Probier's. In der StoppHttp-Methode solltest Du mit etwas Glück nur Disconnect aufrufen.

ManuMF 18. Jun 2007 14:28

Re: Exception bei Thread-Verwendung
 
Ja, genau so hab ich es vorher gemacht.

Ich habe das Ganze nun umgesetzt. Es besteht hier aber weiter das Problem, dass das Programm nur regiaert, wenn ich im (synchronisierten) work-Update-Event ProccessMessages ausführe, sonst gar nicht. Ich habe das so wie oben vorgeschlagen angelegt, also im onWork wird eine Prozedur synchronisiert aufgerufen, die die Progresbars setzt.

Liegt es vielleicht daran, dass ich das Uploaden als Funktion anlege, da ich wissen muss, ob er fehlgeschlagen ist? Hier ein bisschen Code:
Delphi-Quellcode:
function TUploadThread.DoUpload(URL: String; Stream: TStream; RCT: String; out AW: String): Boolean;
begin
  IdHTTPC.Request.ContentType := RCT;

  result := true;

  try
    AW := IdHTTPC.Post(URL, Stream);
  except
    result := false;
  end;
end;

// Aufruf in einer "normalen" Prozedur außerhalb des Threads

  if (UploadThread.DoUpload(DURL, Stream, RCT, AW)) then
    LogFeld.Items.Add('  Erfolgreich.')
  else
    [Fehlerbehandlung]
ansonsten wenigstens keine AVs oder sonstige Probleme :-D

alzaimar 18. Jun 2007 15:04

Re: Exception bei Thread-Verwendung
 
Du rufst doch gar keinen Thread auf!

Die Arbeit des Threads wird durch seine Execute-Methode definiert. Dort, und nur dort arbeitet der Thread im Hintergrund.

ManuMF 18. Jun 2007 16:15

Re: Exception bei Thread-Verwendung
 
Ach so. Dann bringt aber der Vorschlag von C.Schoch bzw. DGL-luke nichts, oder? :wiejetzt:

C.Schoch 18. Jun 2007 20:01

Re: Exception bei Thread-Verwendung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,
Klar bringen unsere Vorschläge etwas, du solltest den Thread nur auch mal anschmeißen und nicht eine im Thread deklarierte Funktion aus dem Haupthread aufrufen.

Ich hab mal auf die schnelle ne Demo zusammengebaut allerdings einen Download (Upload ist aber gleich zu implementieren), Fehlerbehandlung usw sind noch nachzurüsten.

Um die Meldung "Fehler" zu provozieren einfach das Programm mir der Firewall blockieren.

Edit: Vieleicht solltest du dich erstmal mit den Grundlagen von Threads vertraut machen z.B. mit Luckies Thread Tutorial (Threads_mit_Delphi.pdf)

ManuMF 18. Jun 2007 22:11

Re: Exception bei Thread-Verwendung
 
(Der Fehler liegt wohl an einem Verständnisproblem. Soweit wie möglich bin ich das Tutorial nämlich schon durchgegangen.)

Aber ich pendele hier ständig von einem Problem zum nächsten: Dein Beispiel ist super (danke dafür!), aber es berücksichtigt wieder nicht, dass ich das IdHTTP per Buttonclick stoppen können muss. Außerdem geschieht der Upload in einer Schleife. Was muss ich da tun? Den Thread jedes mal wieder neu erzeugen und starten?

C.Schoch 19. Jun 2007 18:27

Re: Exception bei Thread-Verwendung
 
Hi,
Ich will dir ja nicht die Lösung auf dem Silbertablett präsentieren, du willst doch auch was lernen oder?

Das mit dem Abbruch ist einfach, hierfür besitzt ein Thread Objekt die Eigenschaft Terminated.

Den Thread würde ich nicht jedes mal neu starten. Ein Ansatz wäre dem Thread eine Liste mit Urls zu übergeben, die er dann abarbeitet.

ManuMF 19. Jun 2007 18:54

Re: Exception bei Thread-Verwendung
 
Sicher will ich was lernen, sonst müsste ich ja immer wieder hier zu Threads nachfragen ;-)

Ich dachte auch schon an Terminated, aber wie mache ich das dem IdHTTP klar? OK, ich könnte es mal im onWork probieren, das wird ja ständig aufgerufen.

Das mit der Liste wäre sehr einfach, wenn ich keine GUI hätte. Sprich: In der Schleife, in der hochgeladen wird, passiert einiges. Ich schreibe da eine Art Log in ein Memo, zeige an, welche Datei er hochlädt, wie groß sie ist etc. Das heißt, ich müsste eine Unzahl an Variablen anlegen, in die das gespeichert wird. Nicht nur das, ich muss auch auf eine Listbox und diverse andere Controls zugreifen, die das Verhalten steuern. Das Ganze erweist sich also als äußerst kompliziert :-( Naja, ich probiers mal.

C.Schoch 19. Jun 2007 19:28

Re: Exception bei Thread-Verwendung
 
Auch ich hätte gerne ein Synchronize das eine Prozedure mit Variablen aufrufen kann.
Da das nicht geht wirst du wohl um die Variablen nicht herumkommen.

Wenns noch Fragen gibt einfach Posten.

ManuMF 19. Jun 2007 20:39

Re: Exception bei Thread-Verwendung
 
Ja, eine wäre da noch (den Rest hab ich geschafft) :-D

Das Problem tritt in folgender Situation auf: Ich starte den Upload mitsamt Thread normal. Mittendrin breche ich ab, rufe also Thread.Terminate auf. Im onWork erkennt er das und disconnected das IdHTTP. Meine Fehlermeldung wird angezeigt. So weit, so gut.
Nun möchte ich aber wieder den Upload starten. Was muss ich dazu aufrufen? So bricht der Thread immer ab, da ja Terminated auf true steht.

Hat sich erledigt, ich erstelle den Thread einfach jedes mal, wenn ich einen Upload beginne.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:55 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz