Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Absturz der Anwendung nach beenden eines Threads (https://www.delphipraxis.net/180808-absturz-der-anwendung-nach-beenden-eines-threads.html)

Captnemo 19. Jun 2014 12:52

Delphi-Version: 5

Absturz der Anwendung nach beenden eines Threads
 
Hi,

ich habe ein Programm, welches zur Runtime einen, oder mehrere Threads erzeugt. In diesen Thread läuft ein TCP-Client (TWSocket) der eine Verbindung zu einem TCP-Server hält.
Wenn nun der TCP-Server sich verabschiedet, schickt er noch ein "Disconnect" rüber, damit sich der Thread mit dem TCP-Client abarbeiten und beenden kann, was er m.E. auch tut.

Allerdings habe ich folgendes Phänomen:
Wenn sie so ein Thread beendet hat, und ich klicke das Formular der Anwendung an, dann bekomme ich eine Zugriffsverletzung bei 0x00000000: Lesen von Adresse 0x00000000, bzw.
System exception (code 0xc000041d) at 0x7702bda1.
Auch innerhalb der IDE.

Wenn ich aber das Formular nicht anklicke, dann läuft das Programm weiter, erzeugt auch neue Thread, und verbindet sich auch per TCP mit dem Server. Das kann ich x-mal machen, solange ich nicht das Formular der Mainform anklicke.

Woher könnte sowas kommen? Wie kann ich feststellen ob der Thread wirklich beendet ist? Ich weiß nicht wirklich wie ich zur Ursache des Problems komme.

PS: Oben steht die falsche Delphi-Version. Ist XE4, hab ich zu spät gesehen

Klaus01 19. Jun 2014 13:11

AW: Absturz der Anwendung nach beenden eines Threads
 
.. aus der Adresse lässt sich schliessen, dass auf eine Object-Instanz zugegriffen wird
die a) noch nicht erstellt wurder oder b) bereits wieder freigegeben wurde.

MadExcept hast Du schon ausprobiert?

Grüße
Klaus

Captnemo 19. Jun 2014 13:19

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von Klaus01 (Beitrag 1262872)
.. aus der Adresse lässt sich schliessen, dass auf eine Object-Instanz zugegriffen wird
die a) noch nicht erstellt wurder oder b) bereits wieder freigegeben wurde.

So hatte ich mir das auch gedacht, aber ich war davon ausgegangen, dass mir die IDE dann auch an die Stelle springt, wo die Exception auftritt.

Zitat:

Zitat von Klaus01 (Beitrag 1262872)
MadExcept hast Du schon ausprobiert?

Das müßte ich mir extra kaufen :(

Das der Fehler nur auftritt, wenn das Formular den Fokus bekommt, denke ich dass es mit irgendwelchen Fenster-Messaging zusammen hängt. Allerdings ist mir der Zusammenhang zwischen den Fensterbotschaften und den Thread nicht klar. Sicher ist nur, dass ich irgendwo eine Fehler habe.

Ich speichere mir die Threads in einer TObjectList. Entfernt sich das Object (der Thread) selber aus dieser Liste wenn er terminiert ist, oder muß ich das selbst machen. Könnte der Fehler vielleicht daher kommen?
Zur Zeit verwende ich die TObjectList noch nicht, ist für später vorgesehen.

Klaus01 19. Jun 2014 13:23

AW: Absturz der Anwendung nach beenden eines Threads
 
.. für den privaten Gebrauch ist madExcept kostenfrei.

Wenn ein Thread in einer TObjectList verwaltet wird terminiert,
wird er nicht aus der Objectliste entfernt.
Woher soll die Objectliste denn wissen ob ein Eintrag nicht mehr valide ist?

Grüße
Klaus

Captnemo 19. Jun 2014 13:31

AW: Absturz der Anwendung nach beenden eines Threads
 
Ich frag jetzt mal ganz blöd:
Wie finde ich den in der TObjectList am sichersten wieder (bzw. er sich selbst) und an welcher Stelle entferne ich ihn aus dieser am besten. Am Ende von der Execute-Methode?

Ansonsten müßte ich ihn noch einen Indikator mit auf den Weg geben z.B. ein Handle, worüber ich ihn wiederfinden kann.

Uwe Raabe 19. Jun 2014 13:41

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von Captnemo (Beitrag 1262873)
Zitat:

Zitat von Klaus01 (Beitrag 1262872)
MadExcept hast Du schon ausprobiert?

Das müßte ich mir extra kaufen :(

Wenn du mit Programmieren Geld verdienst, wie hoch ist dein Stundensatz? Wie viele Stunden müsste dir madExcept ersparen, damit sich die Anschaffung (z.Zt. 159 €) lohnt? Wie lange laborierst du allein an diesem einen Problem schon rum? (Übrigens: you may use the non-commercial edition for 30 days of evaluation).

Für den privaten Gebrauch ist es, wie schon gesagt wurde, kostenlos.

Klaus01 19. Jun 2014 13:47

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von Captnemo (Beitrag 1262875)
Ich frag jetzt mal ganz blöd:
Wie finde ich den in der TObjectList am sichersten wieder (bzw. er sich selbst) und an welcher Stelle entferne ich ihn aus dieser am besten. Am Ende von der Execute-Methode?

Wenn ich Threads in einer Objectliste verwalte, dann ist bei den Threads freeOnTerminate bei mir auf false gesetzt.
Dann kannst Du durch die Objectliste gehen un die Threads auf finished abfragen.
Dann musst Du den Thread freigeben und aus der Liste entfernen.
Wenn bei der Objectlist ownsObject = true ist, dann reicht es den Thread aus der Liste zu löschen.


Grüße
Klaus

Captnemo 19. Jun 2014 13:52

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von Klaus01 (Beitrag 1262879)
Wenn ich Threads in einer Objectliste verwalte, dann ist bei den Threads freeOnTerminate bei mir auf false gesetzt.
Dann kannst Du durch die Objectliste gehen un die Threads auf finished abfragen.
Dann musst Du den Thread freigeben und aus der Liste entfernen.
Wenn bei der Objectlist ownsObject = true ist, dann reicht es den Thread aus der Liste zu löschen.

Okay, das habe ich verstanden. Das durchsehen der ObjectList muß ich ja irgendwie anstoßen. Finished wir ja sicherlich erst gesetzt, wenn die Execute-Methode verlassen wurde. Demnach macht es keinen Sinn darin per PostMessage das in die Wege zu leiten.
Aber einen Timer dafür erscheint mir auch nicht unbedingt sinnvoll, zu mal der (zumindest in meinem Fall) dann x-mal die Liste durchsieht, und meistens halt nix macht.

Klaus01 19. Jun 2014 13:58

AW: Absturz der Anwendung nach beenden eines Threads
 
.. vielleicht kann das Ereignis onTerminate des Theads dazu verwendett werden
eine Message zu schicken.

Grüße
Klaus

mjustin 19. Jun 2014 14:06

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von Captnemo (Beitrag 1262868)
Wenn ich aber das Formular nicht anklicke, dann läuft das Programm weiter, erzeugt auch neue Thread, und verbindet sich auch per TCP mit dem Server. Das kann ich x-mal machen, solange ich nicht das Formular der Mainform anklicke.

Woher könnte sowas kommen?

Aus welcher Library stammt TWSocket, ICS? Von ICS wird ein Fensterhandle benutzt. Eventuell besteht hier ein Zusammenhang?
Zur Verwendung von TWSocket in Hintergrundthreads, die Property 'Multithreaded' und Hinweis auf ein Multihtreaded-Beispiel könnte das hier weiterhelfen:

How can I push a TWSocket's OnDataAvailable() event to a background thread in my Delphi 6 application?

Captnemo 19. Jun 2014 14:26

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von mjustin (Beitrag 1262884)
Zitat:

Zitat von Captnemo (Beitrag 1262868)
Wenn ich aber das Formular nicht anklicke, dann läuft das Programm weiter, erzeugt auch neue Thread, und verbindet sich auch per TCP mit dem Server. Das kann ich x-mal machen, solange ich nicht das Formular der Mainform anklicke.

Woher könnte sowas kommen?

Aus welcher Library stammt TWSocket, ICS? Von ICS wird ein Fensterhandle benutzt. Eventuell besteht hier ein Zusammenhang?
Zur Verwendung von TWSocket in Hintergrundthreads, die Property 'Multithreaded' und Hinweis auf ein Multihtreaded-Beispiel könnte das hier weiterhelfen:

How can I push a TWSocket's OnDataAvailable() event to a background thread in my Delphi 6 application?

Ja, ist von ICS. Das mit Multithreaded hatte ich schon gefunden und verwende das auch. Das war auch mein erste Gedanke, da ich da eine Zusammenhang vermutete.
Grundsätzlich gehe ich aber mal davon aus, dass eher ich einen Fehler mache als Francois Piette :)

mjustin 19. Jun 2014 14:32

AW: Absturz der Anwendung nach beenden eines Threads
 
Läßt sich das Problem anhand eines minimalen Beispielprojekts reproduzieren (das man dann hier posten könnte)?

madExcept würde ich bei Abstürzen auch als allererstes benutzen um den Callstack zu erhalten. (es ist fast schon ein must-have Werkzeug).

Captnemo 19. Jun 2014 15:34

AW: Absturz der Anwendung nach beenden eines Threads
 
Also ich habe mir jetzt im Thread im OnTerminate per PostMessage eine Message an den Hauptthread schicken lassen.

Dann rufe ich folgende Procedure auf

Delphi-Quellcode:
  Writelog('Message TCPComThreadEnded empfangen');
  for I := ComThreadList.Count-1 downto 0 do
  begin
    if TTCPThread(ComThreadList[i]).Finished then
    begin
      Writelog('FreeAnNil TCPComThread');
      TTCPThread(ComThreadList[i]).Free;
      Writelog('Thread aus TObjectList entfernen');
      ComThreadList.Delete(i); //<- Hier tritt eine Exception auf, dass das Object nicht mehr da ist.
    end;
  end;
Erzeugen tu ich es so:
Delphi-Quellcode:
  TCPThread:=TTCPThread.Create(False, '192.168.177.71', localport, ip, port, self.Handle);
  ComThreadList.Add(TCPThread);
Muß ich es auf der ComThreadList nicht mehr löschen?

Wenn ich bei ComThreadList.Delete(i) eine Haltepunkt setze, und alle im Einzelschritt durchgehe, dann lande ich in der Unit "System.Classes" in der Funktion "TThread.destroy".
Das kommt aber wahrscheinlich durch den Aufruf von .Free (2 Zeilen drüber).

Und ich lande hier:
Delphi-Quellcode:
destructor TThread.Destroy;
begin
  if (FThreadID <> 0) and not FFinished and not FExternalThread then
  begin
    Terminate;
    if FCreateSuspended or FSuspended then
      Resume;
    WaitFor;
  end;
  RemoveQueuedEvents(Self);
{$IF Defined(MSWINDOWS)}
  if (FHandle <> 0) and not FExternalThread then CloseHandle(FHandle);          //<- Hier habe ich eine Exception:
       // Im Project WSPRG.exe ist eine Exception der Klasse $C00000005 mit der
       // Meldung 'Zugriffsverletzung bei 0x00000000: Lesen von Adresse 0x00000000' aufgetreten


{$ELSEIF Defined(POSIX)}
  // This final check is to ensure that even if the thread was never waited on
  // its resources will be freed.
  if (FThreadID <> 0) and not FExternalThread then pthread_detach(pthread_t(FThreadID));
{$IF Defined(MACOS)}
  pthread_mutex_destroy(FCreateSuspendedMutex);
{$ELSEIF Defined(LINUX)}
  sem_destroy(FCreateSuspendedSem);
{$ENDIF LINUX}
{$ENDIF POSIX}
  inherited Destroy;
  FFatalException.Free;
end;

Uwe Raabe 19. Jun 2014 15:42

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von Captnemo (Beitrag 1262890)
Wenn ich bei ComThreadList.Delete(i) eine Haltepunkt setze, und alle im Einzelschritt durchgehe, dann lande ich in der Unit "System.Classes" in der Funktion "TThread.destroy".
Das kommt aber wahrscheinlich durch den Aufruf von .Free (2 Zeilen drüber).

Das kommt eher daher, daß das Delete auch gleichzeitig die Instanz freigibt, die dann natürlich nicht mehr existiert. Lass doch mal das Free zwei Zeilen drüber weg.

Captnemo 19. Jun 2014 16:37

AW: Absturz der Anwendung nach beenden eines Threads
 
Okay, das funktioniert :-) Danke Uwe.

Allerdings besteht mein ursprüngliches Problem immer noch.
Jetzt habe ich mir mal das MADExcept heruntergeladen und auch in den madexcept Settings aktiviert. Meine Exe wird auch größer, und jetzt sollte doch eigentlich bei einer Exception ein Fenster mit Debuginfo's kommen. Allerdings bekomme ich nach wie vor entweder die Fehlermeldung von Windows, oder er geht ins Debugging der IDE. Muß man noch was anderes machen, damit madexcept die Exception abfängt?

himitsu 19. Jun 2014 16:39

AW: Absturz der Anwendung nach beenden eines Threads
 
Entweder du sagst der Objektliste die soll das löschen (OwnsObjects) und selber löschst du das nicht mehr,
wobei hier das Delete die TThread-Instance löscht.

Aber wenn du das unbedingt selber löschen willst, dann darf entwedet die Liste das nicht automatisch löschen (kein OwnsObjects)
oder du mußt den "ungültigen" Zeiger via TObjectList.Extract rausholen.

Captnemo 19. Jun 2014 16:44

AW: Absturz der Anwendung nach beenden eines Threads
 
Ich habe jetzt OwnObjects:=False und lösche das Object jetzt selber. Das Free hab ich rausgenommen und so funktioniert es jetzt auch.
Aber mein Ursprüngliches Problem ist noch da und das mit dem madexcept will auch nicht funktionieren (Wär ich heut bloß im Bett geblieben)

Uwe Raabe 19. Jun 2014 16:49

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von Captnemo (Beitrag 1262901)
Jetzt habe ich mir mal das MADExcept heruntergeladen und auch in den madexcept Settings aktiviert. Meine Exe wird auch größer, und jetzt sollte doch eigentlich bei einer Exception ein Fenster mit Debuginfo's kommen. Allerdings bekomme ich nach wie vor entweder die Fehlermeldung von Windows, oder er geht ins Debugging der IDE. Muß man noch was anderes machen, damit madexcept die Exception abfängt?

Der IDE-Debugger hat Vorrang. Wenn du das Programm dann in der IDE weiterlaufen lässt, sollte madExcept zuschlagen. Oder einfach ohne Debugger starten.

Wenn Windows die Exception fängt, dann müsste man das mal genauer untersuchen, wo die Exception hochkommt. Hast du alle Checks (Range checking, Overflow checking) aktiviert?

Captnemo 19. Jun 2014 17:24

AW: Absturz der Anwendung nach beenden eines Threads
 
Liste der Anhänge anzeigen (Anzahl: 1)
Okay, das mit den madexcept läuft jetzt. Ich habe eine bugreport, aus dem ich selbst leider nicht so viel herauslesen kann. Ich häng den mal an Anhang dran, vielleicht kann jemand etwas daraus erkennen.

Wenn ich dann in der madException auf Continue Application klicke, läuft meine Anwendung scheinbar weiter, bis ich der Mainform mal wieder den Focux spendiere.

himitsu 19. Jun 2014 17:37

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von Captnemo (Beitrag 1262904)
Ich habe jetzt OwnObjects:=False und lösche das Object jetzt selber. Das Free hab ich rausgenommen und so funktioniert es jetzt auch.
Aber mein Ursprüngliches Problem ist noch da und das mit dem madexcept will auch nicht funktionieren (Wär ich heut bloß im Bett geblieben)

Du hast jetzt das Free weggemacht und das OwnObjects auch und das FreeOnTerminate ist ebenfalls nicht aktiv?
Es gibt also nur noch das Delete in der Liste.

Nja, dann hast du den Thread-Zeiger nun aus der Liste, aber die Thread-Instanz gammelt als Speicherleck immernoch im Programm rum.
Einwas davon mußt du schon noch machen (nur Eines und nicht Mehreres).

Captnemo 19. Jun 2014 20:13

AW: Absturz der Anwendung nach beenden eines Threads
 
Sorry, Ownobjects ist natürlich auf True. Hatte mich vertippt.

Captnemo 20. Jun 2014 06:52

AW: Absturz der Anwendung nach beenden eines Threads
 
Liste der Anhänge anzeigen (Anzahl: 2)
Guten Morgen,

neuer Tag, neues Glück.

Da mein ursprünglicher Fehler immer noch existiert, steige ich an dieser Stelle noch mal ein.

Wie bereits gesagt, wird eine Exception ausgelößt, wenn mein Thread mit dem TCP-Client (TWSocket von ICS) beendet wird bzw. beendet ist, und ich anschließen der Mainform den Focus geben, z.B. durch anklicken.
Was dann im Detail passiert kann ich schwer sagen. Aber ich nehme mal an, dass Windows sicherlich eine Window-Message schickt, deren Verarbeitung dann, aus welchen Gründen auch immer, fehlschlägt.

In meinem Programm fange ich im Grunde keinerlei Messages ab, bis auf eine einzige, die mein Thread an die Mainunit schickt wenn er sich beendet, aber die habe ich erst später hinzugefügt. Der Fehler war schon vorher da.
Leider weiß ich mir nicht zu helfen.

Wenn ich den Thread nicht erzeuge, und dem zur Folge auch nicht beende, tritt natürlich kein Problem auf.

Zu der Exception springt mir die der Debugger der IDE an folgende Stelle:
Delphi-Quellcode:
{ Standard window procedure }
function StdWndProc(Window: HWND; Message: UINT; WParam: WPARAM; LParam: WPARAM): LRESULT; stdcall;
{$IF Defined(CPUX86)}
{ In   ECX = Address of method pointer }
{ Out  EAX = Result }
asm
        XOR    EAX,EAX
        PUSH   EAX
        PUSH   LParam
        PUSH   WParam
        PUSH   Message
        MOV    EDX,ESP
        MOV    EAX,[ECX].Longint[4]
        CALL   [ECX].Pointer
        ADD    ESP,12                //<- Genau hier hin.
        POP    EAX
end;
Ich habe mal eine Screenshot von der IDE an dieser Stelle gemacht und angehängt. Vielleicht hat ja irgendjemand noch eine Idee, was ich machen könnte um dem Fehler auf die Spur zu kommen.

Meinen Thread häng ich auch noch mal dran, möglicherweise liegt der Fehler ja da drin.

himitsu 20. Jun 2014 07:22

AW: Absturz der Anwendung nach beenden eines Threads
 
Die Fehlerstelle ist hier eine Zeile vorher, denn leider zeigt der Debugger die Position der Rücksprungadresse an.

Der Fehler ist also in dem CALL aufgetreten, bzw. in der aufgerufenen Methode.

Zitat:

Aber ich nehme mal an, dass Windows sicherlich eine Window-Message schickt, deren Verarbeitung dann, aus welchen Gründen auch immer, fehlschlägt.
Dem würde ich mal zustimmen.

In welchem Thread-Kontext liegt das denn? (würde zwar MainThread vermuten, aber kann nicht schaden mal nachzusehn -> Thread-Status)

Captnemo 20. Jun 2014 07:32

AW: Absturz der Anwendung nach beenden eines Threads
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hier ist der Thread-Status.
Ich muß zugeben, dass mein Wissen für die Beurteilung ob das nun der MainThread ist, nicht ausreicht.
Was ich aber sehe, dass er wohl auf eine Adresse zeigt $00000000, die wohl nicht der MainThread sein dürfte. Sondern wohl eher mein TCP-Thread, der ja nicht mehr existiert.

Da stellt sich mir gleich mal die Frage, wer schickt eine Fensterbotschaft an meinen (nicht mehr existierenden) Thread? Und das erste was mir dazu einfällt wäre ICS TWSocket, welches mit einen unsichtbaren Fenster im Hintergrund arbeitet (hab ich gelesen).
Das TWSocket ist aber mit Free entfernt...hm...ich dreh mich im Kreis und mir wird schwindelig :pale:

Hier mal der Screenshot vom Thread-Status:

ensaron 20. Jun 2014 08:28

AW: Absturz der Anwendung nach beenden eines Threads
 
Hallo Captnemo,

vielleicht gibt es einen Konflikt beim Empfangen von Messages? Wenn die Messagenummer für ICS nicht explizit auf einen Startwert gesetzt wird, benutzt ICS als erste Nummer
Delphi-Quellcode:
WM_USER + 1
. Ich bin mir zwar nicht sicher, ob das zu einem Problem führen kann, aber den ICS-Messages einen Startwert zu geben, kann ja nicht schaden.
Um den Startwert zu setzen, benutze die Variable
Delphi-Quellcode:
GWndHandlerMsgLow
in der Unit
Delphi-Quellcode:
OverbyteIcsWndControl
, bevor du deine erste ICS-Komponente erzeugst.

Grüße
Thomas

Captnemo 20. Jun 2014 08:46

AW: Absturz der Anwendung nach beenden eines Threads
 
Danke Thomas, das werde ich berücksichtigen.

Aber ich glaube ich bin dem Fehler auf die Spur gekommen.
Ich habe mal alle Objecte die ich im Create erzeuge auskommentiert, und dann läuft mein Thread, läßt sich beende und alle ist Okay.

Dann habe ich die schrittweise wieder eingebaut, und siehe da, als einen Timer wieder aufgenommen habe, tritt der Fehler wieder aus.
Ohne jetzt noch alle anderen Objecte zu testen (was ich aber noch mache) würde ich dann vielleicht hier den Fehler erst mal suchen.

Also im Thread.Create erzeuge ich den timer:
Delphi-Quellcode:
FUpdateTimer:=TTimer.Create(Nil);
und im meiner Execute sieht's so aus:
Delphi-Quellcode:
procedure TTCPThread.Execute;
begin
  Try
    FUpdateTimer.Interval:=60000;
    Synchronize(
      Procedure
      begin
        frm_main.Writelog('Init TCP-Connection ('+FBindIP+'@'+IntToStr(FBindPort)+')>('+FHost+'@'+IntToStr(FPort)+')');
      end
    );
    //FTCPClient.Connect;


    while not Terminated do begin
      sleep(100);
      self.Terminate;
      if Terminated then
      begin
//        FUpdateTimer.Enabled:=False;
        break;
      end;
    end;
  finally
    Synchronize(
      Procedure
      begin
        frm_main.ReleasePort(FBindPort);
      end
    );
    FUpdateTimer.Free;
    Synchronize(
      Procedure
      begin
        frm_main.Writelog('Thread beenden');
      end
    );
  end;
end;
Was ist denn daran falsch? Ich erzeuge ihn....mach aber nix damit...und gebe ihn wieder frei. :gruebel:

himitsu 20. Jun 2014 08:49

AW: Absturz der Anwendung nach beenden eines Threads
 
:gruebel:
Nachdem ein Thread beendet wurde, wird dessen MessageQueue gelöscht (falls er Eine hat), kurz davor die verknüpften Windows (vermute ich mal) und man kann an ihn dann auch keine Message mehr senden. (eigentlich)

Falls meine "Vermutung" nicht stimmt, dann würden die Windows ja in der Luft hängen, da ihre Messages immer nur im verknüpften Thread abgearbeitet werden. (Dem, wo das Control erstellt wurde)


Die MessageQueue eines Threads wird beim ersten Zugriff generiert, erstes PostThreadMessage an den Thread,
oder beim Erstellen eines Window in diesem Thread.


[add]
Zitat:

Delphi-Quellcode:
FUpdateTimer.Free;

Der Timer wurde im Hauptthrad erstellt (zumindestens da, wo TTCPThread.Create ausgeführt wurde).
Damit gehört er zur nicht-threadsicheren VCL des Hauptthreads und gehört auch nur dort zerstört (Synchronize).

Auch das Enabled gehört nicht in den Thread.

Außer du erstellst den Timer im Thread und mußt deinem Thread natürlich auch eine Message-Verarbeitung spendieren, denn ohne werden die Messages des Timers dann nie verarbeitet.



[add2]
Zitat:

Delphi-Quellcode:
      self.Terminate;
      if Terminated then
      begin
        break;
      end;

Ergibt das nicht einfach nur ein
Delphi-Quellcode:
Exit;
?

Captnemo 20. Jun 2014 08:53

AW: Absturz der Anwendung nach beenden eines Threads
 
Hab grad den Test umgekehrt gemacht. Nur TTimer weglassen, schon läuft mein Thread ohne Fehler und Probleme.

Nur was jetzt? TTimer im TThread...müßte doch gehen.

Captnemo 20. Jun 2014 09:00

AW: Absturz der Anwendung nach beenden eines Threads
 
Grad gefunden:

Zitat:

To have the TTimer.OnTimer event be triggered in the context of the worker thread, you have to instantiate the TTimer inside the thread's Execute() method instead. But that has another set of pitfalls. TTimer creates a hidden window using AllocateHWnd(), which is not thread-safe and cannot safely be used outside the context of the main thread. Also, TTimer requires the creating thread context to have an active message loop, which your thread does not.
Quelle: http://stackoverflow.com/questions/1...d-generates-av

:wall::wall:

Gibt's nen Timer der Threadsafe ist?

Ist der JvThreadTimer Theadsafe?
Zitat:

This component is a replacement for the TTimer component with a better accuracy (1 millisecond) and without consuming a window handle for the timer. TJvThreadTimer uses an internal thread instead of the Windows API timer functions, and can have an accuracy of a millisecond, but it will consume more CPU than a TTimer.
http://wiki.delphi-jedi.org/wiki/JVC...TJvThreadTimer
Versteh ich das richtig?

mkinzler 20. Jun 2014 09:09

AW: Absturz der Anwendung nach beenden eines Threads
 
TTimer verwendet die Funktion setTimer von Windows. Du könntest das manuell versuchen.

himitsu 20. Jun 2014 09:10

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von Captnemo (Beitrag 1262999)
Grad gefunden:

Siehe hatte es auch grade noch so gesehn und meinen Beitrag oben erweitert.
Vorallem das Fette und Nachfolgendes.

himitsu 20. Jun 2014 09:14

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von mkinzler (Beitrag 1263001)
TTimer verwendet die Funktion setTimer von Windows. Du könntest das manuell versuchen.

TTimer oder ein eigenes MessageOnlyWindow+SetTimer bringt nichts, solange die "komplette" Bahandlung nicht auf einen der beiden Threads beschränkt wird.

Captnemo 20. Jun 2014 09:19

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von himitsu (Beitrag 1262995)
Zitat:

Delphi-Quellcode:
      self.Terminate;
      if Terminated then
      begin
        break;
      end;

Ergibt das nicht einfach nur ein
Delphi-Quellcode:
Exit;
?

Meines Wissens wir bei einem Exit die Procedure/Function verlassen, während ein Break nur die Schleife (for, while, Loop) verläßt.

Hilfeauszug:

Exit:
Zitat:

Beendet die aktuelle Prozedur.

In Delphi entzieht die Prozedur Exit der aktuellen Prozedur sofort die Steuerung. Wenn die aktuelle Prozedur das Hauptprogramm ist, bewirkt Exit die Beendigung des Programms.

Exit veranlasst die aufrufende Prozedur, mit der Anweisung nach dem Punkt fortzufahren, an dem die Prozedur aufgerufen wurde.

Anmerkung: Exit entzieht der aktuellen Prozedur die Steuerung, nicht nur dem aktuellen Block. Aber Exit verletzt den Steuerungsfluss nicht, der durch ein try..finally-Konstrukt vorgeschrieben ist; wenn Exit in der try-Klausel aufgerufen wird, wird die finally-Klausel dennoch ausgeführt.
Break:
Zitat:

Beendet eine for-, while- oder repeat-Anweisung vorzeitig.

In Delphi bewirkt Break, dass eine for, while oder repeat-Schleife verlassen und die Ausführung mit der nächsten Anweisung fortgesetzt wird.

Wird Break außerhalb einer for-, while- oder repeat-Anweisung aufgerufen, gibt der Compiler eine Fehlermeldung aus.

Anmerkung: Break wirkt sich nicht auf die Ablaufsteuerung von try..finally-Konstrukten aus. Wenn Sie Break in der try-Klausel aufrufen, wird die Ausführung in der finally-Klausel fortgesetzt.
Du hast zwar in sofern Recht, als dann der finally-Abschnitt ausgeführt wird, aber wenn man nach der Schleife noch was machen möchte, was nicht in den Finally-Abschnitt gehört, dann ist es nicht das gleiche.


Oder meintest du mein Terminate vor der Schleife?
Das war nur zu Testzwecken drin, damit sich der Thread gleich wieder beendet, und ich somit testen konnte ob irgendeine andere Procedure für den Fehler verantwortlich war.

himitsu 20. Jun 2014 09:22

AW: Absturz der Anwendung nach beenden eines Threads
 
Ja, das Break verlässt die Schleife und das Exit auch.
Im Grunde wollte ich nur sagen, daß die Execute-Methode bei allen 3. Varianten verlassen (Exit sagt das nur deutlicher, zum Programmierer) und der Thread beendet wird. :angel:
Zitat:

Oder meintest du mein Terminate vor der Schleife?
Jupp, genau das.



Ob der TJvThreadTimer threadsave ist, weiß ich nicht, aber ich glaub das "Thread" im Namen sagt erstmal nur aus, wie er intern arbeitet.

TTimer geht über SetTimer und wartet auf die WM_TIMER.
Und der TJvThreadTimer erzeugt einen Thread, in dem er die Millisekunden wartet und dann das Ereignis manuell auslöst, ohne über die MessageQueue zu gehen.

Captnemo 20. Jun 2014 09:26

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von ensaron (Beitrag 1262989)
Hallo Captnemo,

vielleicht gibt es einen Konflikt beim Empfangen von Messages? Wenn die Messagenummer für ICS nicht explizit auf einen Startwert gesetzt wird, benutzt ICS als erste Nummer
Delphi-Quellcode:
WM_USER + 1
. Ich bin mir zwar nicht sicher, ob das zu einem Problem führen kann, aber den ICS-Messages einen Startwert zu geben, kann ja nicht schaden.
Um den Startwert zu setzen, benutze die Variable
Delphi-Quellcode:
GWndHandlerMsgLow
in der Unit
Delphi-Quellcode:
OverbyteIcsWndControl
, bevor du deine erste ICS-Komponente erzeugst.

Grüße
Thomas

Da du dich ja offensichtlich mit TWSocket schon tiefer befasst hast, noch mal eine kleine Nebenfrage.
Ich schicke zeilenweise (TCP) mit Linemode=Enabled und Lineend=#13#10.
Leider kommt aber beim Empfänger nicht immer die vollständige Zeile an. Zu 80% ist alles richtig und zwischendurch werden Zeichen "verschluckt", und zwar immer am Anfang der Zeile.
Ist der Linemode hier grundsätzlich sicher? Bzw. auf der anderen Seite das OnDataAvailable?

mkinzler 20. Jun 2014 09:30

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von Captnemo (Beitrag 1263006)

Da du dich ja offensichtlich mit TWSocket schon tiefer befasst hast, noch mal eine kleine Nebenfrage.
Ich schicke zeilenweise (TCP) mit Linemode=Enabled und Lineend=#13#10.
Leider kommt aber beim Empfänger nicht immer die vollständige Zeile an. Zu 80% ist alles richtig und zwischendurch werden Zeichen "verschluckt", und zwar immer am Anfang der Zeile.
Ist der Linemode hier grundsätzlich sicher? Bzw. auf der anderen Seite das OnDataAvailable?

Das wäre imho in einem eigenen Thread besser aufgehoben

Captnemo 20. Jun 2014 09:33

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von himitsu (Beitrag 1263005)
Und der TJvThreadTimer erzeugt einen Thread, in dem er die Millisekunden wartet und dann das Ereignis manuell auslöst, ohne über die MessageQueue zu gehen.

Das sollte doch eigentlich Threadsafe bedeuten.

Ich habe jetzt den TJvThreadTimer an Stelle des TTimer verwendet und Schwupps....alles Prima.

Ich arbeite noch nicht lange mit Threads, bzw. hatte früher nie die Notwendigkeit. Doch nun geht es nicht anders, und ich stelle langsam fest wie wichtig es ist Threadsafe zu arbeiten. Das Prinzip ist schon klar, doch bei der Umsetzung tappt man doch in so manche Falle ;)
Dank des Forums und dank euch lern ich das auch noch :-D:-D

Captnemo 20. Jun 2014 09:37

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von mkinzler (Beitrag 1263007)
Zitat:

Zitat von Captnemo (Beitrag 1263006)

Da du dich ja offensichtlich mit TWSocket schon tiefer befasst hast, noch mal eine kleine Nebenfrage.
Ich schicke zeilenweise (TCP) mit Linemode=Enabled und Lineend=#13#10.
Leider kommt aber beim Empfänger nicht immer die vollständige Zeile an. Zu 80% ist alles richtig und zwischendurch werden Zeichen "verschluckt", und zwar immer am Anfang der Zeile.
Ist der Linemode hier grundsätzlich sicher? Bzw. auf der anderen Seite das OnDataAvailable?

Das wäre imho in einem eigenen Thread besser aufgehoben

Du meinst so:

Im TCP-Server im OnSessionAvailable die neue Session im Thread erzeugen und dort im OnDataAvailable alle ankommen in einen Messegebuffer vom Mainthread, und dort verarbeiten?

mkinzler 20. Jun 2014 09:38

AW: Absturz der Anwendung nach beenden eines Threads
 
Nein in einem eigenen Beitrag hier im Forum!

himitsu 20. Jun 2014 09:39

AW: Absturz der Anwendung nach beenden eines Threads
 
Zitat:

Zitat von Captnemo (Beitrag 1263010)
Das sollte doch eigentlich Threadsafe bedeuten.

Njain.

Ich sag mal so:
Du hast eine Komponente erstellt
und nur weil sie ein einem anderem Thread verwendet wird, ist sie damit nicht automatisch threadsave. :zwinker:

Das kommt dann drauf an, wie die Steuerung arbeitet und ob sie eventuell entsprechend abgesichert ist, also vorallem dein Setzen des Intervalls oder des Enable.
Das Free dagegen rufe man ja eh fast immer aus einem anderem Thread auf, womit es da weniger Probleme gibt. Aber vermutlich werden die das wohl bedacht haben.

Und dann kommt es auch noch darauf an, ob die das Timer-Event synchronisieren. (wobei ich das jetzt nicht glaub, da der Timer dann ja ungenauer laufen würde)


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:27 Uhr.
Seite 1 von 2  1 2      

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