Threads stürzen bei DLL Aufruf ab
Moderator: Moderatoren
-
- UDF-Programmierer
- Beiträge: 51
- Registriert: Di, 18. Okt 2005 12:35
- Wohnort: 41747 Viersen
- Kontaktdaten:
Threads stürzen bei DLL Aufruf ab
Hallo,
ich habe das Problem das 2 meiner Threads abstürzen nachdem ich eine Funktions ausführe. Diese Function binde ich vorher über DLL Function ein. Jemand eine Idee woran das liegen könnte.
Vielen Dank schonmal
ich habe das Problem das 2 meiner Threads abstürzen nachdem ich eine Funktions ausführe. Diese Function binde ich vorher über DLL Function ein. Jemand eine Idee woran das liegen könnte.
Vielen Dank schonmal
-
- UDF-Programmierer
- Beiträge: 51
- Registriert: Di, 18. Okt 2005 12:35
- Wohnort: 41747 Viersen
- Kontaktdaten:
- brandelh
- Foren-Moderator
- Beiträge: 15696
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 66 Mal
- Danksagung erhalten: 33 Mal
- Kontaktdaten:
Hi,
Zur Problemeingrenzung schlage ich wie immer vor:
so müsste man feststellen können wo das Problem liegt.
Potentielle Probleme kommen von Public, Private, Static Variablen,
Annahmen zur Reihenfolge der Ausführung (diese stimmen fast nie bei mehreren Threads), Dateizugriffen in eine Datei ...
Dann vergleichen mit dem Ablauf im Hauptthread ...
Vielleicht hilft es ja
Zur Problemeingrenzung schlage ich wie immer vor:
Code: Alles auswählen
procedure main
...
set alternate to debug.txt
set alternate on
set console off // wichtig bei reiner GUI Anwendung !
...
function DieAbstürzendeFunktion()
? "ThreadID",ThreadID(),seconds()
...
? "vor ..."
...
? "nach ..."
...
return ...
Potentielle Probleme kommen von Public, Private, Static Variablen,
Annahmen zur Reihenfolge der Ausführung (diese stimmen fast nie bei mehreren Threads), Dateizugriffen in eine Datei ...
Dann vergleichen mit dem Ablauf im Hauptthread ...
Vielleicht hilft es ja
Gruß
Hubert
Hubert
-
- UDF-Programmierer
- Beiträge: 51
- Registriert: Di, 18. Okt 2005 12:35
- Wohnort: 41747 Viersen
- Kontaktdaten:
Hallo,
konnte das Problem lösen, lag an einem Fehler in der DLL der dann die Threads hat mitabstürzen lassen.
Habe aber gleich noch ein Problem mit Threads, oder vielleicht verstehe ich da auch was noch nicht so ganz.
Wir sind gerade bei der Migration unseres alten Clipper Programmes nach Xbase, das geht bei uns leider nur immer Stück für Stück da auch das alte Programm parallel noch weiterentwickelt werden muss. Wir haben ein Xbase Programm das die ganze Zeit im Hintergrund läuft um Aufgaben zu erfüllen die vom Clipper Programm nicht mehr erfüllt werden können oder die wir schon umgestellt haben. Das Programm guckt (wenn es nicht gerade ein Programm ausführt) jede Sekunde in eine Datenbank ob vom Clipper Programm ein neuer Auftrag da ist.
Rufe ich jetzt über dieses Programm z.B. meinen Drucken Dialog auf funktioniert dort der Eventhandler nicht mehr / bzw. kaum noch. Die Fenster lassen sich nicht mehr schließen und reagieren nicht mehr auf Benutzerdefinierte Events die ich mittels PostAppEvent sende. Hat jemand eine Ahnung was das sein könnte?
Grüße
konnte das Problem lösen, lag an einem Fehler in der DLL der dann die Threads hat mitabstürzen lassen.
Habe aber gleich noch ein Problem mit Threads, oder vielleicht verstehe ich da auch was noch nicht so ganz.
Wir sind gerade bei der Migration unseres alten Clipper Programmes nach Xbase, das geht bei uns leider nur immer Stück für Stück da auch das alte Programm parallel noch weiterentwickelt werden muss. Wir haben ein Xbase Programm das die ganze Zeit im Hintergrund läuft um Aufgaben zu erfüllen die vom Clipper Programm nicht mehr erfüllt werden können oder die wir schon umgestellt haben. Das Programm guckt (wenn es nicht gerade ein Programm ausführt) jede Sekunde in eine Datenbank ob vom Clipper Programm ein neuer Auftrag da ist.
Rufe ich jetzt über dieses Programm z.B. meinen Drucken Dialog auf funktioniert dort der Eventhandler nicht mehr / bzw. kaum noch. Die Fenster lassen sich nicht mehr schließen und reagieren nicht mehr auf Benutzerdefinierte Events die ich mittels PostAppEvent sende. Hat jemand eine Ahnung was das sein könnte?
Grüße
- brandelh
- Foren-Moderator
- Beiträge: 15696
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 66 Mal
- Danksagung erhalten: 33 Mal
- Kontaktdaten:
Hallo,
da braucht man mehr infos.
1. ruft das Überwachungsprogramm alle Sekunde z.B. mit TimerEvent die Überprüfung auf ? Wenn ja, könnte hier ein Mehrfachaufruf stattfinden.
2. Ist die Druckfunktion in einem eigenen Thread ?
3. Wenn die Oberfläche eines Programmes nicht mehr reagiert, weil z.B. eine lange For Next Schleife abgearbeitet wird oder die Datenbankabfrage ewig dauert, dann liegt das meist daran, dass keine Threads benutzt werden. Das BS gibt zwar Rechenzeit an jeden Thread, aber innerhalb des Threads wird nur eine Aufgabe erledigt. Wenn nun eine längere Schleife durchlaufen wird, kann nicht gleichzeitig die EventVerarbeitung aktiv sein. Daher sollte man solchen längeren Schleifen auslagern. Oder zwischendurch die Eventschleife aufrufen.
da braucht man mehr infos.
1. ruft das Überwachungsprogramm alle Sekunde z.B. mit TimerEvent die Überprüfung auf ? Wenn ja, könnte hier ein Mehrfachaufruf stattfinden.
2. Ist die Druckfunktion in einem eigenen Thread ?
3. Wenn die Oberfläche eines Programmes nicht mehr reagiert, weil z.B. eine lange For Next Schleife abgearbeitet wird oder die Datenbankabfrage ewig dauert, dann liegt das meist daran, dass keine Threads benutzt werden. Das BS gibt zwar Rechenzeit an jeden Thread, aber innerhalb des Threads wird nur eine Aufgabe erledigt. Wenn nun eine längere Schleife durchlaufen wird, kann nicht gleichzeitig die EventVerarbeitung aktiv sein. Daher sollte man solchen längeren Schleifen auslagern. Oder zwischendurch die Eventschleife aufrufen.
Gruß
Hubert
Hubert
- AUGE_OHR
- Marvin
- Beiträge: 12906
- Registriert: Do, 16. Mär 2006 7:55
- Wohnort: Hamburg
- Hat sich bedankt: 19 Mal
- Danksagung erhalten: 45 Mal
moin,
SLEEP() zum "timeout" in der AppEvent Schleife fehlt. Da durch
nimmt sich der 2st Thread die "ganze Zeit" sodas der 1st Thread
dann "träge" reagiert.
gruss by OHR
Jimmy
Die Frage ist wie das "timeout" erreicht wird ? nEvent == xbe_None ?ab-software hat geschrieben: Das Programm guckt (wenn es nicht gerade ein Programm ausführt)
jede Sekunde in eine Datenbank ob vom Clipper Programm ein neuer
Auftrag da ist.
ohne den code zu sehen würde ich einfach mal tippen das einab-software hat geschrieben: Rufe ich jetzt über dieses Programm z.B. meinen Drucken Dialog auf funktioniert dort der Eventhandler nicht mehr / bzw. kaum noch. Die Fenster lassen sich nicht mehr schließen und reagieren nicht mehr auf Benutzerdefinierte Events die ich mittels PostAppEvent sende. Hat jemand eine Ahnung was das sein könnte?
SLEEP() zum "timeout" in der AppEvent Schleife fehlt. Da durch
nimmt sich der 2st Thread die "ganze Zeit" sodas der 1st Thread
dann "träge" reagiert.
gruss by OHR
Jimmy
-
- UDF-Programmierer
- Beiträge: 51
- Registriert: Di, 18. Okt 2005 12:35
- Wohnort: 41747 Viersen
- Kontaktdaten:
Hallo,
also mein Thread ruft alle paar Sekunden (über set Inverfall) eine Funktion auf die dann je nach eintrag in der Datenbank das jeweilige Programm aufruft. Die Programme sind alle in Xbase DLL's ausgelagert um Updates beim Kunden so einfach wie möglich zu gestalten. Soweit ich weiß wartet der Thread auf die beendigung der Funktion und wird dann erst neu gestartet d.h. mehrfach aufrufe dürften nicht zustande kommen. Ich hatte die Druckfunktion auch schon in einem eigenen Thread konnte aber keinen Unterschied feststellen. Die Druckfunktion hat aber einen eigenen Eventhandler.
also mein Thread ruft alle paar Sekunden (über set Inverfall) eine Funktion auf die dann je nach eintrag in der Datenbank das jeweilige Programm aufruft. Die Programme sind alle in Xbase DLL's ausgelagert um Updates beim Kunden so einfach wie möglich zu gestalten. Soweit ich weiß wartet der Thread auf die beendigung der Funktion und wird dann erst neu gestartet d.h. mehrfach aufrufe dürften nicht zustande kommen. Ich hatte die Druckfunktion auch schon in einem eigenen Thread konnte aber keinen Unterschied feststellen. Die Druckfunktion hat aber einen eigenen Eventhandler.
- andreas
- Der Entwickler von "Deep Thought"
- Beiträge: 1902
- Registriert: Mi, 28. Sep 2005 10:53
- Wohnort: Osnabrück
- Hat sich bedankt: 4 Mal
- Kontaktdaten:
1. Laufen deine Threads ständig
2. oder werden über SetInterval jede Sekunde aufgerufen
zum 1.
bei jedem Thread kannst eigene Event-Schleife einsetzen.
zum 2.
Jimmy hat recht. du muss dann in den Funktionen, die im Thread ausgeführt werden, SLEEP() verwenden, damit deine Event-Schleife auch Rechenzeit bekommt.
2. oder werden über SetInterval jede Sekunde aufgerufen
zum 1.
bei jedem Thread kannst eigene Event-Schleife einsetzen.
zum 2.
Jimmy hat recht. du muss dann in den Funktionen, die im Thread ausgeführt werden, SLEEP() verwenden, damit deine Event-Schleife auch Rechenzeit bekommt.
- brandelh
- Foren-Moderator
- Beiträge: 15696
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 66 Mal
- Danksagung erhalten: 33 Mal
- Kontaktdaten:
Hallo,
mit der Thread-Eventsteuerung habe ich mich noch nicht befasst, aber das Anlegen von mehreren Eventloops ist nicht unproblematisch.
Falls du wirklich 2 getrennte Threads mit je eigener Eventloop hättest, gäbe es keine Probleme mit der Anzeige. Offensichtlich wartet aber immer einer bis der andere beendet ist und bedient derweil sein eigenes Programm nicht mehr.
Ich habe in meinen Programmen (alles im Hauptthread) einige Druck-, Such-, Im- und Export Vorgänge in eigene Threads ausgelagert, die starten, verursachen keine Bildschirmausgabe und werden nach dem Ende einfach beendet. Eines davon überwacht z.B. ein Verzeichnis auf neue Aufträge, das dürfte deiner DBF Überwachung entsprechen.
Von früher her habe ich oft keine Threads eingesetzt, sondern die Eventloop regelmäßig aufgerufen:
Ich weiß jetzt nicht, ob ich das richtig verstanden habe, aber wenn das Hauptprogram der Threadsteuerung nur immer einen Auftrag erledigt, bis der nächste dran kommen kann, warum dann überhaupt eine Threadsteuerung ? Das aktive Programm wird aber solange keine eigenen Threads mehr abarbeiten können, wie die eigene Eventloop durch warten auf das Funktionsende blockiert ist.
Die Aufgabe müßte asyncron ablaufen und nur der Neustart blockiert werden (durch gobale Variable oder DBF Feld in AuftragsDBF ...), dann würde die Anzeige funktionieren. Oder deine Funktion kann obige Funktion aufrufen, aber bei getrennten Threads geht das glaube ich nicht.
mit der Thread-Eventsteuerung habe ich mich noch nicht befasst, aber das Anlegen von mehreren Eventloops ist nicht unproblematisch.
Falls du wirklich 2 getrennte Threads mit je eigener Eventloop hättest, gäbe es keine Probleme mit der Anzeige. Offensichtlich wartet aber immer einer bis der andere beendet ist und bedient derweil sein eigenes Programm nicht mehr.
Ich habe in meinen Programmen (alles im Hauptthread) einige Druck-, Such-, Im- und Export Vorgänge in eigene Threads ausgelagert, die starten, verursachen keine Bildschirmausgabe und werden nach dem Ende einfach beendet. Eines davon überwacht z.B. ein Verzeichnis auf neue Aufträge, das dürfte deiner DBF Überwachung entsprechen.
Von früher her habe ich oft keine Threads eingesetzt, sondern die Eventloop regelmäßig aufgerufen:
Code: Alles auswählen
Hauptprogramm:
..
doEventloop()
..
In einer Druck-/Verarbeitungsschleife
...
do while ...
doEventLoop(0.01) // 1/100 Sekunde andere Events abarbeiten ...
...
...
*-----------------------------------------------------------------------------
FUNCTION DoEventLoop(nSeconds) // For Next Schleifen unterbrechen und Events verarbeiten !
local nBisSeconds, nEvent, mp1, mp2, oXbp
DEFAULT nSeconds to 0 // Standard ist endlose Ausführung
mp1 := NIL // Wahrnungen verhindern
mp2 := NIL
oXbp := NIL
nBisSeconds := seconds() + nSeconds
DO WHILE .T.
nEvent := AppEvent( @mp1, @mp2, @oXbp, nSeconds)
do case
case nEvent = xbe_None
* nichts tun ist hier Standard
case nEvent = xbeP_Keyboard .and. mp1 == xbeK_F1
* xbeP_HelpRequest erscheinen für jede Xbp Instanz, also zu oft !
MsgBox("Die Hilfe ist für dieses Programm noch nicht erstellt.")
otherwise
oXbp:handleEvent( nEvent, mp1, mp2 )
endcase
if nSeconds > 0 .and. nBisSeconds < seconds() // nur wenn keine endlose Ausführung
exit
endif
ENDDO
return nil
Die Aufgabe müßte asyncron ablaufen und nur der Neustart blockiert werden (durch gobale Variable oder DBF Feld in AuftragsDBF ...), dann würde die Anzeige funktionieren. Oder deine Funktion kann obige Funktion aufrufen, aber bei getrennten Threads geht das glaube ich nicht.
Gruß
Hubert
Hubert
- brandelh
- Foren-Moderator
- Beiträge: 15696
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 66 Mal
- Danksagung erhalten: 33 Mal
- Kontaktdaten:
Hallo,
nochmals zu der Ausführung, bist du sicher, dass ein solcher Thread erst :interval 1/100-Sekunden nach dem Ende wieder den execute Block startet ? Ich hatte es immer so verstanden, dass er nach der Zeit die Ausführung startet, egal ob die letzte fertig war, ich bin mit nicht sicher, das hätte aber Auswirkungen.
nochmals zu der Ausführung, bist du sicher, dass ein solcher Thread erst :interval 1/100-Sekunden nach dem Ende wieder den execute Block startet ? Ich hatte es immer so verstanden, dass er nach der Zeit die Ausführung startet, egal ob die letzte fertig war, ich bin mit nicht sicher, das hätte aber Auswirkungen.
Zuletzt geändert von brandelh am Mi, 26. Jul 2006 12:58, insgesamt 1-mal geändert.
Gruß
Hubert
Hubert
- andreas
- Der Entwickler von "Deep Thought"
- Beiträge: 1902
- Registriert: Mi, 28. Sep 2005 10:53
- Wohnort: Osnabrück
- Hat sich bedankt: 4 Mal
- Kontaktdaten:
Hallo,
ich habe ein Programm, was auf dem Server ständig läft und viele Aufgaben erledigt. Insgesamt laufen bei mir ständig 15 Threads, wobei eine1 davon Main ist und noch einer zu unterschiedlichen Zeiten zus. Threads startet, die nach ablaufen beendet werden. Der gleiche Thread sperrt zu bestimmten Zeiten die Ausführung anderer Prozesse.
Ich habe eine einzige Event-Schleife in Main. Die Ausgabe der Meldungen in ein MLE geht über eine Mehtode aus dem Hauptfenster, die mit SYNC deklariert ist, um die Meldungen nicht zu verlieren.
Bei kritischen Threads, die zuviel Prozessorleistung nehmen und andere Prozesse abbremsen, habe ich in den Schleifen immer SLEEP gesetzt.
Im Hauptfenster kann ich problemlos mit Menus und Unterfenstern arbeiten. Beenden der Threads wird über eine globale Variable gesteuert.
ich habe ein Programm, was auf dem Server ständig läft und viele Aufgaben erledigt. Insgesamt laufen bei mir ständig 15 Threads, wobei eine1 davon Main ist und noch einer zu unterschiedlichen Zeiten zus. Threads startet, die nach ablaufen beendet werden. Der gleiche Thread sperrt zu bestimmten Zeiten die Ausführung anderer Prozesse.
Ich habe eine einzige Event-Schleife in Main. Die Ausgabe der Meldungen in ein MLE geht über eine Mehtode aus dem Hauptfenster, die mit SYNC deklariert ist, um die Meldungen nicht zu verlieren.
Bei kritischen Threads, die zuviel Prozessorleistung nehmen und andere Prozesse abbremsen, habe ich in den Schleifen immer SLEEP gesetzt.
Im Hauptfenster kann ich problemlos mit Menus und Unterfenstern arbeiten. Beenden der Threads wird über eine globale Variable gesteuert.
-
- UDF-Programmierer
- Beiträge: 51
- Registriert: Di, 18. Okt 2005 12:35
- Wohnort: 41747 Viersen
- Kontaktdaten:
Hier mal der genauer Aufbau meines Programmes
Sobald ich versuche mit PostAppEvent zu posten wird dieses nicht berücksichtigt. Wo müsste ich das sleep einbauen?
Code: Alles auswählen
PROCEDURE MAIN()
oThread := absThread():new()
oThread:start("abs2Xbase", "")
oThread:setInterval(100)
// Eventhandler
RETURN
PROCEDURE abs2Xbase
// Auftrag aus Datenbank laden
IF cAuftrag == 'print'
print(cParameter);
ENDIF
RETURN
FUNCTION print(cParameter)
// Druckfunktion mit eigenem Eventhandler
RETURN lReturn
- andreas
- Der Entwickler von "Deep Thought"
- Beiträge: 1902
- Registriert: Mi, 28. Sep 2005 10:53
- Wohnort: Osnabrück
- Hat sich bedankt: 4 Mal
- Kontaktdaten:
Code: Alles auswählen
PROCEDURE MAIN()
oThread := absThread():new()
oThread:start("abs2Xbase", "")
oThread:setInterval(100)
// Eventhandler
RETURN
Richtig wäre:
Code: Alles auswählen
PROCEDURE MAIN()
oThread := absThread():new()
oThread:setInterval(100)
oThread:start("abs2Xbase", "")
// Eventhandler
RETURN
- AUGE_OHR
- Marvin
- Beiträge: 12906
- Registriert: Do, 16. Mär 2006 7:55
- Wohnort: Hamburg
- Hat sich bedankt: 19 Mal
- Danksagung erhalten: 45 Mal
hi,
also damit der 1st Eventhandler was bekommt musst du im
2st. Eventhandler ein SLEEP(xx) in deine Schleife mit einbaun.
mir ist auch nicht ganz klar wo dein PostAppEvent herkommt/
hinsoll ? An einen "Dialog" Keyhandler oder an einen Eventloop ?
grundsätzlich könnte man ja alle XbParts mit einem ":Keyboard"
versehen. Ich als alter Cl*pperraner nehme die Tastatur und bin
noch sehr "Masken" orientiert, also werden die xbeP_ Keyboard
jeweils über einen "oDlg:Keyboard" mit dem jeweiligem "Fenster"
(="Maske") verknüpft. Meine XbpPushbutton haben übrigen im
:activate Codeblock meinsten den Cl*pper "Tastencode" im
PostAppEvent() stehen.
Was für einen Event willst du senden ?
xbeP_ (Keyboard), xbeM_(Maus) oder xbeP_User +1 ?
also bitte zeigt uns deine Eventhandler und wo/was ausgelöst
oder ausgewertert wird.
wie fängst du in "abs2Xbase" eigendlich einen "zweiten" Aufruf ab ?
... wenn er in "print" > setInterval(100) verweilt käme ja dann
automatisch ein "weiterer" Aufruf ...
gruss by OHR
Jimmy
gerade der interessante Teil fehlt : Die Eventhandler !ab-software hat geschrieben:Sobald ich versuche mit PostAppEvent zu posten wird diesesCode: Alles auswählen
PROCEDURE MAIN() ... // 1st. Eventhandler RETURN PROCEDURE abs2Xbase .... FUNCTION print(cParameter) // Druckfunktion mit eigenem 2st. Eventhandler RETURN lReturn
nicht berücksichtigt. Wo müsste ich das sleep einbauen?
also damit der 1st Eventhandler was bekommt musst du im
2st. Eventhandler ein SLEEP(xx) in deine Schleife mit einbaun.
mir ist auch nicht ganz klar wo dein PostAppEvent herkommt/
hinsoll ? An einen "Dialog" Keyhandler oder an einen Eventloop ?
grundsätzlich könnte man ja alle XbParts mit einem ":Keyboard"
versehen. Ich als alter Cl*pperraner nehme die Tastatur und bin
noch sehr "Masken" orientiert, also werden die xbeP_ Keyboard
jeweils über einen "oDlg:Keyboard" mit dem jeweiligem "Fenster"
(="Maske") verknüpft. Meine XbpPushbutton haben übrigen im
:activate Codeblock meinsten den Cl*pper "Tastencode" im
PostAppEvent() stehen.
Was für einen Event willst du senden ?
xbeP_ (Keyboard), xbeM_(Maus) oder xbeP_User +1 ?
also bitte zeigt uns deine Eventhandler und wo/was ausgelöst
oder ausgewertert wird.
wie fängst du in "abs2Xbase" eigendlich einen "zweiten" Aufruf ab ?
... wenn er in "print" > setInterval(100) verweilt käme ja dann
automatisch ein "weiterer" Aufruf ...
gruss by OHR
Jimmy
-
- UDF-Programmierer
- Beiträge: 51
- Registriert: Di, 18. Okt 2005 12:35
- Wohnort: 41747 Viersen
- Kontaktdaten:
Code: Alles auswählen
PROCEDURE Main()
LOCAL ;
nEvent := 0 , ;
mp1 := 0 , ;
mp2 := 0 , ;
oXbp := NIL , ;
oTaskMen := NIL
oThread := absThread():new()
oThread:setInterval(100)
oThread:start("abs2Xbase", "")
oTaskBar := TaskBarIcon():New( xbeP_User + 30 ):Create()
oTaskBar:AddIcon( 1, 1 , "ab-software abs2Xbase" )
oTaskMen := XbpMenu():new( oTaskBar):create()
oTaskMen:AddItem( { "Beenden" , { || PostAppEvent(xbeP_User + 1) } } )
ErrorBlock( {|oError| ErrorHandler(oError) })
DO WHILE nEvent <> xbeP_User + 1
nEvent := AppEvent( @mp1, @mp2, @oXbp )
IF nEvent = xbeP_User + 30
IF mp1[2] = xbeM_RbUp
oTaskMen:PopUp( oTaskBar, { mp1[3], mp1[4] } )
ENDIF
ENDIF
IF nEvent == xbeP_User + 1
oTaskBar:RemAllIcons()
ENDIF
oXbp:handleEvent( nEvent, mp1, mp2 )
ENDDO
RETURN
Code: Alles auswählen
PROCEDURE Callabs2Xbase()
// Datenbank öffnen
// Timestamp in eine Datei schreiben damit das ClipperProgramm weiß das wir noch laufen
// Auftrag und parameter auslesen
IF cProgramm == Upper(absBackup)
absBackup()
ENDIF
RETURN
Code: Alles auswählen
FUNCTION absBackup()
* Fenster erstellen
oDlg := dsDialog():new( AppDesktop(), , {370,320}, {400,230}, , .T.)
oDlg:taskList := .T.
oDlg:titleBar := .T.
oDlg:Title := "ab-software Datensicherung "
oDlg:icon := 1 // ab-icon
oDlg:maxButton := .F.
oDlg:minButton := .T.
oDlg:sysMenu := .T.
oDlg:EnableAutoScroll := .F.
oDlg:EnableStatusBar := .F.
oDlg:AutoAccelerator := .F.
oDlg:EnableFocusFrame(.T.)
oDlg:alwaysOnTop := .F.
oDlg:SetFocusFrame( GRA_CLR_GREEN,GRA_CLR_YELLOW,graMakeRGBcolor( {222,222,222} ) )
oDlg:SetQueryClose := {|| PostAppevent(xbeP_User + 2)}
// oDlg:SetQueryClose := {|| PostAppevent(xbeP_Close)}
oDlg:create()
oDlg:toTop()
// Rest des Dialogs aufbauen
* Schließen Button
oClose := dsPushButton():new( drawingArea, , {10+50,105}, {125,70}, )
oClose:caption := "Daten einspielen"
oClose:create()
oClose:Activate := {|| PostAppEvent(xbeP_User +2) }
* Eventloop
DO WHILE nEvent <> xbeP_User +2
* Eventhandler
nEvent := AppEvent( @mp1, @mp2, @oXbp )
oXbp:handleEvent( nEvent, mp1, mp2 )
IF nEvent == xbeP_User +2
oDlg:hide()
oDlg:EndDialog()
ENDIF
ENDDO
//DO WHILE nEvent <> xbeP_Close
// * Eventhandler
// nEvent := AppEvent( @mp1, @mp2, @oXbp )
// oXbp:handleEvent( nEvent, mp1, mp2 )
// IF nEvent == xbeP_Close
// oDlg:hide()
// oDlg:EndDialog()
// ENDIF
//ENDDO
RETURN lReturn
nein da der Thread erst neugestartet wurde wenn der vorherige aufruf fertig abgearbeitet ist. Was er ja erst ist wenn der Dialog beendet wurde.wie fängst du in "abs2Xbase" eigendlich einen "zweiten" Aufruf ab ?
... wenn er in "print" > setInterval(100) verweilt käme ja dann
automatisch ein "weiterer" Aufruf ...
Also ich in dem Dialog versuche die Benutzerdefinierten Events zu posten reagiert der Dialog entweder garnicht oder beendet sich und alle anderen laufenden Threads ohne irgendeine Fehlermeldung.
Benutze ich das Standart xbeP_Close Event funktioniert der Dialog ohne Probleme.
- brandelh
- Foren-Moderator
- Beiträge: 15696
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 66 Mal
- Danksagung erhalten: 33 Mal
- Kontaktdaten:
Hallo,
ich würde das ganze einfacher aufbauen ...
Im aufgerufenen Thread selbst wird die Funktion aufgerufen und dort dann in einer eigenen eventloop alles verarbeitet. Da die Main aber nicht wartet und getrennt ist, wird die main beim Anzeigen nie behindert.
Innerhalb deines 2. Threads kann es nun passieren, dass das dortige Window durch eine lange Verarbeitungsfolge nicht aktualisiert wird, dann muss man dort in regelmäßigen Abständen appevent aufrufen, siehe hierzu meine schon gepostete Eventloopfunktion. Oder man lagert das dann auch in einen weiteren Thread aus.
Eventuell muss man noch syncronisieren oder weitere Flagvariablen (public oder static über funktion) einbauen, ich glaube aber nicht, dass ein Thread einem anderen etwas mit AppEvent senden kann.
ich würde das ganze einfacher aufbauen ...
Code: Alles auswählen
procedure main
memvar IsTreadRunning, IsTreadToKill, nNextTreadStart
public nNextTreadStart := 0 // wird bei Ende von gestartetem
// Thread auf seconds()+1 gesetzt.
public IsTreadRunning := .f. // oder über Funktion mit STATIC
public IsTreadToKill := .f. // diese Vars steuern den Tread ...
...
DO WHILE nEvent <> xbeP_Close
nEvent := AppEvent( @mp1, @mp2, @oXbp, 100 ) // maximal 1 Sekunde warten
* Events verbiegen kann man hier, aber aufpassen, SEHR KURZ halten !
if nEvent # xbe_None // ein Event ist eingetreten
oXbp:handleEvent( nEvent, mp1, mp2 )
endif
if IsTreadRunning // Thread läuft schon ...
nNextTreadStart := nSeconds()+1
else
if nNextTreadStart <= nSeconds()
IsTreadToKill := .f.
oThread := absThread():new()
oThread:start("abs2Xbase", "")
// der Thread muss am Anfang IsTreadRunning := .t. setzen !
endif
endif
if Abbruchbedingung was weiß ich was
// der Thread muss diese Var überprüfen und sich beenden.
// dabei muß er diese wieder auf .f. setzen.
IsTreadToKill := .t.
endif
ENDDO
... dies läuft alles im Hauptthread und ist schnell genug, dass nichts anbrennt...
Innerhalb deines 2. Threads kann es nun passieren, dass das dortige Window durch eine lange Verarbeitungsfolge nicht aktualisiert wird, dann muss man dort in regelmäßigen Abständen appevent aufrufen, siehe hierzu meine schon gepostete Eventloopfunktion. Oder man lagert das dann auch in einen weiteren Thread aus.
Eventuell muss man noch syncronisieren oder weitere Flagvariablen (public oder static über funktion) einbauen, ich glaube aber nicht, dass ein Thread einem anderen etwas mit AppEvent senden kann.
Gruß
Hubert
Hubert
- AUGE_OHR
- Marvin
- Beiträge: 12906
- Registriert: Do, 16. Mär 2006 7:55
- Wohnort: Hamburg
- Hat sich bedankt: 19 Mal
- Danksagung erhalten: 45 Mal
hi,
Dialog bei "xbeP_User +2" geschlossen und sonst kommt der Event
nicht mehr vor ... ?
komisch ist auch die verwendung von "xbeP_User +2". geht das wirklich
"so", oder muss man nicht ein "#define xbeP_User +2 blabla" setzten ?
... auch "liest" es sich besser wenn man die Konstante dort stehen hat.
gruss by OHR
Jimmy
... hm ... das kann ich so nicht erkennen. im 2st. Thread wird derab-software hat geschrieben:Code: Alles auswählen
FUNCTION absBackup() * Eventloop DO WHILE nEvent <> xbeP_User +2 * Eventhandler nEvent := AppEvent( @mp1, @mp2, @oXbp ) oXbp:handleEvent( nEvent, mp1, mp2 ) IF nEvent == xbeP_User +2 oDlg:hide() oDlg:EndDialog() ENDIF // // hier ein SLEEP(10) einbauen // SLEEP(10) ENDDO
nein da der Thread erst neugestartet wurde wenn der vorherige aufruf fertig abgearbeitet ist. Was er ja erst ist wenn der Dialog beendet wurde.wie fängst du in "abs2Xbase" eigendlich einen "zweiten" Aufruf ab ?
... wenn er in "print" > setInterval(100) verweilt käme ja dann
automatisch ein "weiterer" Aufruf ...
Dialog bei "xbeP_User +2" geschlossen und sonst kommt der Event
nicht mehr vor ... ?
komisch ist auch die verwendung von "xbeP_User +2". geht das wirklich
"so", oder muss man nicht ein "#define xbeP_User +2 blabla" setzten ?
... auch "liest" es sich besser wenn man die Konstante dort stehen hat.
gruss by OHR
Jimmy
- brandelh
- Foren-Moderator
- Beiträge: 15696
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 66 Mal
- Danksagung erhalten: 33 Mal
- Kontaktdaten:
Hallo Jimmy,
oder
schreibt.
alles was man mit #define setzt, wird vor dem compilieren wieder durch den Preprozessor ausgetauscht. Für Xpp ist es also egal ob manAUGE_OHR hat geschrieben:hi,
komisch ist auch die verwendung von "xbeP_User +2". geht das wirklich
"so", oder muss man nicht ein "#define xbeP_User +2 blabla" setzten ?
Code: Alles auswählen
#define MyEvent xbeP_User +2
...
if MyEvent ...
Code: Alles auswählen
if xbeP_User +2 ...
genau deshalb und auch wegen der einfacheren Wartbarkeit (1 Stelle ändern und keine Tippfehler ...) sollte man define verwenden.AUGE_OHR hat geschrieben: ... auch "liest" es sich besser wenn man die Konstante dort stehen hat.
Gruß
Hubert
Hubert
-
- UDF-Programmierer
- Beiträge: 51
- Registriert: Di, 18. Okt 2005 12:35
- Wohnort: 41747 Viersen
- Kontaktdaten: