Seite 1 von 2
Zugriff auf Thread-Window über Hauptprozess
Verfasst: 12.05.2010 20:18
von benji
Hallo Leute!
Ich schreibe zur Zeit einen Updater, der es erfordert, dass wärend des Window-Loops gleichzeitig die Update-Routine Dateien herunterlädt und ein paar Gadgets aktualisiert.
Was ich haben will ist folgendes:
Während des updatens soll die GUI voll funktionsfähig sein - und auch aktualisiert werden.
Aber:
Ich komme mit Threads noch nicht so klar - und immer wenn ich versuche zb die Update-Routine (die die Gadgets aktualisiert) in einen Thread auszulagern wird mir im debugger ausgegeben, dass das angegebene Gadget nicht initialisiert wurde. (vermutlich, weil Threads nen eigenen Speicherbereich bekommen?)
Und wenn ich es anders herum (Window und Loop im Thread) versuche, klappts auch nicht (bzw irgendwas mache ich falsch

).
So sieht der Call zur Zeit aus:
Code: Alles auswählen
Open_main(progressbar_elements) ;--> main window
If CreateThread(@mainloop(), dummy)
Updateroutine(md5_handle) ;--> Hier greift der UpdateProzess, der auf Gadgets im Open_main zugreift
Else
MessageRequester("Fehler", "Fehler beim erstellen des Threads")
EndIf
Hoffe ihr könnt etwas mit meinen Spärlichen informationen anfangen!
Viele Grüße, benji!

Re: Zugriff auf Thread-Window über Hauptprozess
Verfasst: 12.05.2010 20:39
von ts-soft
Erstellen, Event-Ereignisse abfragen usw. funktioniert nur in dem Thread, wo das Main-Fenster erstellt wurde!
Das einzige, was Du in Threads machen kannst, ist SetGadgetText, State usw., wobei das auch alles mit
vorsicht zu geniessen ist. Am besten machen Threads nichts mit dem Fenster und seinen Childs, sondern
melden lediglich ans MainLoop (SendMessage) das was zu tun ist.
Re: Zugriff auf Thread-Window über Hauptprozess
Verfasst: 12.05.2010 20:46
von benji
ts-soft hat geschrieben:Erstellen, Event-Ereignisse abfragen usw. funktioniert nur in dem Thread, wo das Main-Fenster erstellt wurde!
Das einzige, was Du in Threads machen kannst, ist SetGadgetText, State usw., wobei das auch alles mit
vorsicht zu geniessen ist. Am besten machen Threads nichts mit dem Fenster und seinen Childs, sondern
melden lediglich ans MainLoop (SendMessage) das was zu tun ist.
okay umgestellt, der Thread erstellt nun ein Window und hat den MainWindowLoop drin. Aber die UpdateRoutine kann vom Hauptprozess nicht auf die Gadgets zugreifen(die vom Thread erstellt wurden) - bekomme immer einen Gadget not initialized Error...
Re: Zugriff auf Thread-Window über Hauptprozess
Verfasst: 12.05.2010 20:49
von ts-soft
Sag erst mal, was Du damit meinst auf die Gadgets zugreifen und besser mal einen ausführbaren Beispielcode
damit man eine Vorstellung bekommst, was Du da vorhast.
Das überprüfen mit IsGadget usw., sollte man grundsätzlich in Threads und Callbacks machen!
Re: Zugriff auf Thread-Window über Hauptprozess
Verfasst: 12.05.2010 20:57
von benji
ts-soft hat geschrieben:Sag erst mal, was Du damit meinst auf die Gadgets zugreifen und besser mal einen ausführbaren Beispielcode
damit man eine Vorstellung bekommst, was Du da vorhast.
Das überprüfen mit IsGadget usw., sollte man grundsätzlich in Threads und Callbacks machen!
Mit Zugriefen meine ich AddGadgetItem (in eine Liste, die im Thread erstellt wurde)
Da es sich um ein kommerzielles Projekt handelt poste ich nur ungern meinen source. Aber ich hoffe, dass dieser Abschnitt alles soweit klärt
Code: Alles auswählen
Procedure UpdateRoutine(md5handle)
Repeat
in.s = ReadString(md5handle)
If Len(in) > 1
If FindString(in, "[", 0)
relativepath.s = Mid(in, 2, Len(in) -2)
Else
md5sum.s = in
EndIf
Else
UpdateFile(relativepath, md5sum)
count + 1
SetGadgetState(progress, count)
; SetGadgetState(#progress, count)
EndIf
Until Eof(md5handle) <> 0
CloseFile(md5handle)
DeleteFile("md5")
updated = 1
;---Autostartbuttoncode---;
; If GetGadgetState(#autostart) = #PB_Checkbox_Checked
; RunProgram("notepad.exe")
; EndIf
; ProcedureReturn 1
EndProcedure
Procedure Open_main(progressbar_elements)
If OpenWindow(#main, 652, 375, 311, 201, "Notepad Launcher " + version + " Build: "+ Str(#PB_Editor_BuildCount), #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered )
ButtonGadget(#start, 190, 160, 110, 30, "Starten")
GadgetToolTip(#start, "führt Notepad aus")
CheckBoxGadget(#autostart, 70, 160, 110, 20, "automatisch Starten")
GadgetToolTip(#autostart, "Nach dem Update Notepad automatisch ausführen")
ProgressBarGadget(#progress, 10, 130, 290, 20, 0, progressbar_elements)
ListViewGadget(#list, 10, 10, 290, 110)
If autostart
SetGadgetState(#autostart, #PB_Checkbox_Checked)
EndIf
EndIf
EndProcedure
Procedure mainloop(*dummy)
Open_main(progressbar_elements)
Repeat ; Start of the event loop
Event = WaitWindowEvent() ; This line waits until an event is received from Windows
WindowID = EventWindow() ; The Window where the event is generated, can be used in the gadget procedures
GadgetID = EventGadget() ; Is it a gadget event?
EventType = EventType() ; The event type
;You can place code here, and use the result as parameters for the procedures
If Event = #PB_Event_Gadget
If GadgetID = #start
If updated
RunMMOGrinder()
End
Else
MessageRequester("Bitte warten...", "Bitte warten sie bis der Update-Vorgang beendet ist.")
EndIf
ElseIf GadgetID = #autostart
If GetGadgetState(#autostart) = #PB_Checkbox_Checked And autostart = false
filehandle = OpenFile(#PB_Any ,ini_file)
If filehandle
FileSeek(filehandle, Lof(filehandle))
If IsEntryPresent(filehandle, "[Settings]")
WriteStringN(filehandle, "autostart=true")
; SetGadgetState(#autostart, #PB_Checkbox_Checked)
autostart = true
Else
WriteStringN(filehandle, "")
WriteStringN(filehandle, "[Settings]")
WriteStringN(filehandle, "autostart=true")
; SetGadgetState(#autostart, #PB_Checkbox_Checked)
autostart = true
EndIf
Else
MessageRequester("Fehler", "Fehler beim Speichern, der Datei "+ini_file)
EndIf
CloseFile(filehandle)
ElseIf GetGadgetState(#autostart) = #PB_Checkbox_Unchecked And autostart = true
filehandle = OpenFile(#PB_Any ,ini_file)
If filehandle
FileSeek(filehandle, Lof(filehandle))
If IsEntryPresent(filehandle, "[Settings]")
DeactivateEntry(filehandle, "autostart=")
autostart = false
EndIf
Else
MessageRequester("Fehler", "Fehler beim Speichern, der Datei "+ini_file)
EndIf
CloseFile(filehandle)
EndIf
ElseIf GadgetID = #progress
ElseIf GadgetID = #list
EndIf
EndIf
Delay(50)
Until Event = #PB_Event_CloseWindow ; End of the event loop
End
EndProcedure
;-----MAIN
If CreateThread(@mainloop(), dummy)
Updateroutine(md5_handle)
Else
MessageRequester("Fehler", "Fehler beim erstellen des Threads")
EndIf
Re: Zugriff auf Thread-Window über Hauptprozess
Verfasst: 12.05.2010 21:07
von ts-soft
So ist das leider nicht Testbar und hellsehen kann ich auch nicht
Das Delay(50) im MainLoop ist natürlich sehr böse, den solltest Du in jedem Falle
dort sofort entfernen.
Re: Zugriff auf Thread-Window über Hauptprozess
Verfasst: 12.05.2010 21:11
von benji
ts-soft hat geschrieben:So ist das leider nicht Testbar und hellsehen kann ich auch nicht
Das Delay(50) im MainLoop ist natürlich sehr böse, den solltest Du in jedem Falle
dort sofort entfernen.
Das hab ich gemacht.
Hum... okay... hier poste ich mal den gesamten source.... :/
Bitte vertraulich behandeln.
EDIT
Ich will haben, dass das window voll funktionsfähig ist (wie im eventloop) und von der update-procedure das Listgadget und die Processbar aktualisiert werden und danach das Programm auf eine Usereingabe wartet.
Re: Zugriff auf Thread-Window über Hauptprozess
Verfasst: 12.05.2010 21:19
von ts-soft
Dein geheimer Code ist nicht so wichtig, eher ein ausführbarer Code, aufs minimalste gekürzt, der das Problem
aufzeigt.
Dir ist hoffentlich klar, das kurz nach dem Starten des Threads Dein Programm zuende ist?
Das kann nicht funktionieren.
Re: Zugriff auf Thread-Window über Hauptprozess
Verfasst: 12.05.2010 21:40
von benji
ts-soft hat geschrieben:Dein geheimer Code ist nicht so wichtig, eher ein ausführbarer Code, aufs minimalste gekürzt, der das Problem
aufzeigt.
das war ja nicht böse gemeint^^
ts-soft hat geschrieben:Dir ist hoffentlich klar, das kurz nach dem Starten des Threads Dein Programm zuende ist?
Das kann nicht funktionieren.
Ja ist mir klar, da kann ich ja dann wiederum den check einbauen, ob das window closed wurde.
Das Problem, dass der debugger den Error ausspuckt besteht aber leider weiterhin...
Mit geht es um die AddGadgetItem Funktion. Bei jedem call kommt die Ausgabe, dass das Gadget nicht initialisiert wurde.
Re: Zugriff auf Thread-Window über Hauptprozess
Verfasst: 12.05.2010 21:59
von ts-soft
Erstmal zu Deinen "kommerziellen" Code
1. GetCurrentDirectory wird nicht immer den richtigen Pfad zurückgeben, z. B. wenn das Programm
über eine Shell gestartet wurde. Da das Programm Admin-Rechte benötigt, ist es sogar sehr wahrscheinlich,
das es über eine Shell gestartet wird, weil der Admin wird sich dafür nicht an den PC das Benutzers setzen.
2. Die Notepad-Procedure ist ja schon gemeingefährlich.
3. Ohne EnableExplicit, mal werden Variablen deklariert, mal nicht, diese 400 Zeilen sind auch für Dich in wenigen
Wochen nicht mehr nachvollziehbar.
Ich möchte ehrlich gesagt kein Kunde von Dir sein
Aber egal, soll nicht mein Problem sein.
Hier der Beweis das AddGadgetItem funktioniert
Code: Alles auswählen
EnableExplicit
Global stopthread
Procedure MyAddItem(void)
Protected value
While Not stopthread
value + 1
If IsGadget(0)
AddGadgetItem(0, -1, Str(value))
EndIf
Delay(5000)
Wend
EndProcedure
Define thread
If OpenWindow(0, 0, 0, 270, 140, "ListViewGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ListViewGadget(0, 10, 10, 250, 120)
thread = CreateThread(@MyAddItem(), 0)
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
stopthread = #True
WaitThread(thread)
EndIf
Gruß
Thomas