AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Brauche ich einen Thread ?

Ein Thema von TERWI · begonnen am 15. Sep 2009 · letzter Beitrag vom 17. Sep 2009
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
378 Beiträge
 
Delphi 11 Alexandria
 
#1

Brauche ich einen Thread ?

  Alt 15. Sep 2009, 17:54
Ich hab hier nen DVB-Programm, für welches ich eine (nicht die erste...) DLL als Plugin geschrieben habe.
Ich lasse mir von dort über eine CallBack-Routine EPG-Daten geben und füttere damit fortlaufend meine eigene Datenbank.
Dabei prüfe ich, ob neue Daten gekommen sind und ob ich meine Anzeige ggf. Updaten muss.
Dazu muss ist logo die Daten - hängen erst mal in div. TList's aus Record's - auf mal in meiner DLL 'anfassen'.

Jetzt ist kommen diese Daten natürlich nicht regelmäßig und gelegentlich auch in Massen nacheinander.
Erwartungsgemäß kommt es zu Access-Violations....

Ich hatte das zuerst mit einem Thread versucht, in dem die CB läuft. Das ging irgendwie aber gar nicht.
Dann habe ich es mittels Holzhammermethode nun erst mal so gelöst:

Ein Timer ruft im Sekundentakt und sperrt zu Anfang mittels einer globalen Variablen IGNORE_CB := true die CallBack-Funktion.
(prüft Ignore-CB und exit...)
So wird erfolgreich nichts an den Daten geändert (hinzufügen, ändern, löschen).
Ich kann dann so lange wie ich will mit den Daten was anstellen.
Am Ende der Timer-Funktion setze ich IGNORE_CB wieder auf false.
Damit verpasse ich ggf. ne Menge (vorhandener) Daten, aber die wiederholen sich ja fortlaufend.

Neuerdings bekomme ich aber sporadisch und nicht wirklich nachvollziehbar wieder Zugriffsverletzungen.
An der Programmstruktur habe ich nichts weiter geändert...

Hat jemand ne schlauere Idee ?
Hab ich was mit dem Thread falsch aufgezogen ?
Muss man sonst noch was beachten ?

Ergänzung:
Ich habe mal ein CriticalSection.Enter an den Anfang und ein Leave ans Ende der CallBack gestellt.
Ändert auch nicht wirklich was an gelegentlichen Zugriffsverletzungen.
  Mit Zitat antworten Zitat
furuha

Registriert seit: 21. Jan 2009
21 Beiträge
 
Delphi 2005 Personal
 
#2

Re: Brauche ich einen Thread ?

  Alt 15. Sep 2009, 19:07
Meiner Meinung nach ist dein posting zu unkonkret gehalten. Quellcode auszüge usw. wären mal gut.
Die Fehler können ja in deiner DLL sein, in der Prüfroutine, in der DB bzw dem Zugriff auf diese.....da gibt es ja grenzenlose Möglichkeiten

mfg
Furuha
  Mit Zitat antworten Zitat
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
378 Beiträge
 
Delphi 11 Alexandria
 
#3

Re: Brauche ich einen Thread ?

  Alt 15. Sep 2009, 19:35
Sorry, was ist daran unkonkret ?

Hier geht es mir darum, das eine 'fremde' App eine Routine meines Programmes in nicht bekannten Abständen in nicht bekannter Häufigkeit mit nicht bekannter Datenmenge bzw. Zeitbeanspruchung aufruft.
Eben in / mit benannter CallBack-Routine meines Proggies, die ich der aufrufenden App zuvor in eine Intialisierung mitteile.

Wenn du all den Code dazu lesen und verstehen möchtest, müsste ich hier gut einige tausend Zeilen posten, die du dann versuchen kannst in der Komplexität zu verstehen. Ich arbeite da seit gut 2 Jahren dran...

Meine Frage war eigentlich nur:
Wie handle ich diese externen calls ?

Mit einem Thread hat es wie gesagt gar nicht geklappt - warum auch immer. Falscher Ansatz ?
Mit meinem 'Hammer' ging es ewig bis vor kurzen gut. Nun hab ich sporadische Probs.

Mir gehts erst mal um den Ansatz. Details kommen da sicher noch.
  Mit Zitat antworten Zitat
furuha

Registriert seit: 21. Jan 2009
21 Beiträge
 
Delphi 2005 Personal
 
#4

Re: Brauche ich einen Thread ?

  Alt 15. Sep 2009, 21:51
Sinnvoll wäre ja vllt, herauszufinden, was genau die Zugriffsverletzung auslößt.
Wenn es einige Zeit lief, wird sich ja schon etwas geändert haben? Haben sich vllt ein paar EPG Daten geändert?
Denn wenn es schon "ewig" lief kann der Ansatz/die Lösung(auch wenns ein Holzhammer ist) nicht so falsch sein.(Auch wenn es evtl schönere Lösungen gibt - aber was spricht gegen Holzhämmer und Workarounds, solange sie funktionieren, und das hat es ja bis Tag x)

Wenn sich an deinem programm nichts geändert hat dann ja nur entweder an den EPG Daten oder am DVB Programm.

Furuha


PS: Ich versuche im Moment lediglich den Fehler einzukreisen. Vllt hilft das ja auch schjon ein wenig. Aber ich nehme sowieso an, das du auf die oben genannten Punkte eh schon gekommen bist.
  Mit Zitat antworten Zitat
Klaus01
Online

Registriert seit: 30. Nov 2005
Ort: München
5.755 Beiträge
 
Delphi 10.4 Sydney
 
#5

Re: Brauche ich einen Thread ?

  Alt 15. Sep 2009, 22:15
Guten Abend,

vielleicht hast Du ja die Chance madExcept einzubinden.

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.135 Beiträge
 
Delphi 12 Athens
 
#6

Re: Brauche ich einen Thread ?

  Alt 15. Sep 2009, 22:20
Zitat von Klaus01:
vielleicht hast Du ja die Chance madExcept einzubinden.
die ganzen delphiinternen Prüfungen sind auch aktiviert?

siehe Projektoptionen > Überlauf-, Indexprüfungen und Dergleichen
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
378 Beiträge
 
Delphi 11 Alexandria
 
#7

Re: Brauche ich einen Thread ?

  Alt 16. Sep 2009, 18:33
Wie der Titel vermuten lässt, bin ich nicht der Held in Sachen Threads, weil ich damit eher nicht arbeite und diese bisher auch nicht wirklich einsetzen musste.

Versuche ich noch mal eine Erklärung:

Ist allein die CallBack-Routine aktiv und lässt sich durch das DVB-Prog regelmäig 'anschieben', übergebene EPG-Daten mit vorhandenen Daten in meinen Listen aus Records und Arrays auf Aktualität zu prüfen und ggf. neue Daten zu schreiben, ist alles in bester Ordnung.
Da alles dynamisch ist (und sein muss), prüfe ich penibelst auf ungültige Zeiger, Array-Größen, u.s.w.
Diese Routinen sind auch schon etwa 2 Jahre alt und laufen in einer Vorgängerversion in anderer Konstellation problemlos.
Das kann (und hat) wochenlang laufen ohne einen Fehler, Hänger oder sonst was.

Neben den globalen EPG-Daten beschreibe ich weitere globale Variablen, in denen ich mir die Anzahl der aktuell vorhandenen (ggf. upgedateten) EPG-Datensätze (integer, wird max. 50-60.000) merke und was zuletzt gemacht wurde -> Datensatz neu oder update (beides boolean).


Die zeite wichtige Funktion ist ein Timer mit Intervall := 1000.
Hier prüfe ich zunächst mit einer ebenfalls globalen Var, ob sich die Anzahl der aktuellen EPG-Daten seit letzem Aufruf verändert hat (if Total_EPG > Total_EPG_Mem then ...).
Ist das nicht der Fall -> exit.
Wenn doch, werden noch die Var EPG_New und EPG-Update evaluiert und entsprechend reagiert.
Die Reaktion besteht für beide eigentlich nur darin darin, das ich die Datenanzeige nur neu aufbaue (neu, ggf. Sortierung) oder einfach nur auffrische (Update).
Mehr passiert da erst mal/eigentlich nicht...
Ach ja - die func übernimmt auch die eigentliche Display-initialisierung nach Laden vorhandener Daten (Total_EPG_Mem = 0).
Auch habe ich hier mal experimentiert und häppchenweise was per zweitem Timer mit zufälligen Zeiten 'angeboten'.
Kein Problem ...

Wie oben beschrieben blockiert der Timer die CallBack so lange, bis die Anzeige (wieder-) hergestellt ist.
Das hat ne kleine Ewigkeit absolut sauber funktioniert.
Nur kommen jetzt GELEGENTLICH Zugriffsverletzungen.

Es kann also nur am 'Zusammenspiel der beiden Funtkionen liegen, denn jede einzeln für sich lüppt bestens.
Da ich 'nur' der Progger bin und mich nicht wirklich mit Interna und dem Ablauf auf Thread- und/oder Prozessor-Ebene beschäftigt habe (und will), vermute ich folgendes:
-> Die Timer-func ist noch nicht fertig und es kommt ein CallBack
-> CallBack schreibt Daten, die der TImer gerade liest oder umgekehrt
oder
-> ... die DLL selbst 'verweigert' die Annahme (zeitkritisch ?) und das DVB-Prog macht die Access-Violation ?

Wie kann ich das effektiv und dauerhaft verhindern ?
Das passiert wie gesagt NICHT immer - gelegentlich ...
Deshalb die Frage: Brauche ich einen Thread ?
... oder löst der das überhaupt ?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.135 Beiträge
 
Delphi 12 Athens
 
#8

Re: Brauche ich einen Thread ?

  Alt 16. Sep 2009, 18:59
Mit Threads mußt du noch mehr auf Synchronisierung und Dergleichen achten ... es kann also nur noch schlimmer werden.

Und da du wärend der Bearbeitung die gleichzeitigen Zugriffe eh blockieren willst, kann man mit einem Thread auch nichts verbessern.

Erstmal sollte man mal rausbekommen was, wo und warum nun diese Zugriffsverletzung verursacht.
Da dieses sich nicht direkt und schnell reproduzieren läßt, würde ich erstmal ein Logging-System einbauen und überall an passenden Stellen einen Eintrag in die Logdatei vornehmen, damit man nun weiß, was zuletzt gemacht wurde.
Auch die Exception würde dann da natürlich mit eingetragen.

Nun kann man sich Stück für Stück und eventuell mit mehreren Anläufen und Anpassen der mitgelogten Arbeitsschritte, an die Fehlerstelle ranpirschen und wenn man weiß woran es nun liegt, ERST dann kann man wirklich etwas dagegen vornehmen.


SO, der Timer läuft ja im Hauptthread.
Und in welchem Kontext wird nun diese CallBack-Prozedur ausgeführt?
> In einem anderem Thread, im Hauptthread oder gar innerhalb der Timer-Prozedur?
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von TERWI
TERWI

Registriert seit: 29. Mär 2008
Ort: D-49626
378 Beiträge
 
Delphi 11 Alexandria
 
#9

Re: Brauche ich einen Thread ?

  Alt 16. Sep 2009, 19:54
Die DLL - wie gesagt für besagtes DVB-Proggie (DVBDream) - beinhaltet:

- 3 Formulare (EPG_MAIN, Scheduler und SetUp)
- 1 Unit (DATA - alle Deklarationen und allgemeine Funktionen zu Daten, in allen Forms eingebunden)
- Init- und Exit-Prozeduren der DLL
- Event-func's des Hauptprogramm's für jeweilige Reaktion (8 Stück)

Via Sendmessage setze ich den Zeiger auf meine CallBack und starte / stoppe ein Delivery nach Bedarf.
Das mache ich aber nur bei Umschaltung auf einen anderen Transponder (andere Daten...).

D.h. mein CallBack wird im 'laufenden Betrieb' kontinuierlich gerufen und abgearbeitet.
Diese Funktion ist in der DATA-Unit deklariert und allen anderen Form's bekannt.
... Keine Ahnung wie sich der Kontext für Zugriffe da verhält. Sollte aber laufen / lief auch bisher.

Die Datenanzeige ist logo eine Form wie Setup und Scheduler.
Wird wie alle anderen in der DLL bei INIT erzeugt und im EXIT zerstört.

JEDE Form hat ihre eigene Initialisierung über eine separate Prozedur, da das bei Create (und Destroy) in der Form noch nicht erledigt werden kann, bzw. noch nicht alle erforderlichen Daten vorhanden sind.
Passiert dann halt bei ON_INIT der DVB-App.
Rückwärts bei Exit: Alle Daten werden bei ON_Exit der DVB_App aus allen Forms gelesen und die Daten gesichert.

Da habe ich lange dran geknobelt, weil das vom zeitlichen Ablauf her nicht so wirklich einfach war, Daten zu intialisieren und vor Programm-Ende auch alle passend zu schreiben.
Das als solches klappt aber sehr gut und ist auch nicht neu. Nur ein wenig überarbeitet und verfeinert...

Aber darum als solche geht es wahrscheinlich ja auch gar nicht. Das Modul/Plugin ist wie gesagt schon gut 2 Jahre alt und hat derzeit in einer etwas anderen Konstellation mit den gleichen Daten-Routinen absolut einwandfrei gefunkt.


Sorry der vermeintlich doofen Frage:
... aber wie bekomme ich denn nun genau heraus, wer oder was den nun die Exception wo verursacht ???
Dazu muss ich zu meiner Schande gestehen (... ja lacht alle nur, höhöhö) das ich bisher immer kleine aber feine Progs gebastelt und das nie gebraucht habe.
Erst denken, dann proggen - hatte ich bisher nie Probs ...
Nur jetzt sch--ßt es mich an.

Help Please !?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.135 Beiträge
 
Delphi 12 Athens
 
#10

Re: Brauche ich einen Thread ?

  Alt 16. Sep 2009, 20:14
In der Exception steht ja eine Adresse, wo sie ausgelößt wurde und diese Adresse könnte man jetzt in seinem Programm suchen. (Debugger > CPU-Ansicht)

Wenn man dazu noch die Debuggerinfos mit einkompiliert hat, wird es einfacher,
aber einige sind ja meißtens automatisch mit drin (da fast keiner sie abschaltet )
und so zeigt der Debugger in der CPU-Ansicht auch oftmals die Befehler und Funktionen mit an.

Man kann sich auch Helfen lassen MadExcept ließt z.B. bei einer Exception noch den Aufrufstack aus und zeigt dann in der Exception direkt die Funktionsnamen und andere Infos an.


Und, wie gesagt, kannst du auch einfach an "wichtigen" Stellen in eine Logdatei scheiten, was gerade gemacht wird und wenn auch die Exception dort eingeschrieben wird, dann liegt der Fehler vermutlich irgendwo hinter dem letzen Eintrag (der Stelle wo dieser Eintrag ins Log geschrieben wurde), welcher vor der Exceotion im Log steht.

Du kannst auch dein Programm mal eine Weile im Debugger laufen lassen, dann stoppt der Debudder das Programm auch an der entsprechenden Stelle.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:07 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