Button soll Schleife unterbrechen (möglichst ohne Threads)
- hjbremer
- Beiträge: 822
- Registriert: 27.02.2006 22:30
- Computerausstattung: von gestern
- Wohnort: Neumünster
Re: Button soll Schleife unterbrechen (möglichst ohne Thread
BindGadgetEvent() ist auch nur eine 2. bzw. zusätzliche Eventverarbeitung.
Außerdem braucht man eine globale Variable, denn irgendwie muß die Schleife abgebrochen werden.
Dies betrifft auch Threads. Wie gesagt man braucht eine Abbruchbedingung.
Einen Thread einfach beenden ohne die Schleife zu beenden, kann Probleme machen.
z.B. das ListIconGadget zu sortieren mit Api Befehlen in einem Thread.
Außerdem ist diese Vorgehensweise mit WindowEvent() und einem Delay z.B. beim WebGadget
und der Busy-Abfrage doch bewährt. Es funktioniert ohne Probleme. Man braucht dafür keinen Thread finde ich.
Außerdem braucht man eine globale Variable, denn irgendwie muß die Schleife abgebrochen werden.
Dies betrifft auch Threads. Wie gesagt man braucht eine Abbruchbedingung.
Einen Thread einfach beenden ohne die Schleife zu beenden, kann Probleme machen.
z.B. das ListIconGadget zu sortieren mit Api Befehlen in einem Thread.
Außerdem ist diese Vorgehensweise mit WindowEvent() und einem Delay z.B. beim WebGadget
und der Busy-Abfrage doch bewährt. Es funktioniert ohne Probleme. Man braucht dafür keinen Thread finde ich.
Purebasic 5.70 x86 5.72 X 64 - Windows 10
Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
- NicTheQuick
- Ein Admin
- Beiträge: 8675
- Registriert: 29.08.2004 20:20
- Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
- Kontaktdaten:
Re: Button soll Schleife unterbrechen (möglichst ohne Thread
hjbremer: (Wait)WindowEvent() an zwei Stellen zu nutzen finde ich nicht so schön. Um Events an verschiedenen Stellen im Programm abarbeiten zu können, gibt es BindEvent() und BindGadgetEvent(). Abgesehen davon funktioniert #WM_KEYDOWN nur unter Windows. Das Delay(1) ist da auch fehl am Platz. Ein Delay(1) ruft man nur auf, wenn WindowEvent() = 0 ist, denn dann gab es auch wirklich kein Event. Gab es ein Event, sollte man so schnell wie möglich das nächste abholen anstatt auch dann zu warten. Dabei ist es egal, ob es ein Delay(1) oder Delay(100) oder sogar Delay(0) ist. In jedem Fall gibt das Betriebssystem die Arbeit an den nächsten Prozess weiter. Und bis dann der eigene Prozess wieder dran ist, kann es mehr als 0 oder 1 Millisekunde dauern. In der Zeit könnten schon wieder neue Events angekommen sein.
Der Pseudocode von man-in-black gefällt mir da wesentlich besser. Aber natürlich funktioniert dein Code in den meisten Fällen trotzdem gut. Es geht aber schöner.
Der Pseudocode von man-in-black gefällt mir da wesentlich besser. Aber natürlich funktioniert dein Code in den meisten Fällen trotzdem gut. Es geht aber schöner.
Re: Button soll Schleife unterbrechen (möglichst ohne Thread
Ich habe es gerade ohne Thread, nur mit PostEvent() versucht, wobei die Suche immer einen Einzelschritt weiter arbeitet wenn ein Such-Event auftritt sodass zwischendurch die anderen Events verarbeitet werden können. Problem dabei ist das PostEvent / CustomEvents scheinbar eine andere Priorität haben, sodass beispielsweise das Disablen eines Buttons vor PostEvent nicht sichtbar wird bis alle Custom Events abgearbeitet sind und keine neuen mehr auftreten, dann ist die Suche ja aber schon wieder vorbei. Weiß nicht wieso sich CustomEvents nicht hinten anstellen.
- NicTheQuick
- Ein Admin
- Beiträge: 8675
- Registriert: 29.08.2004 20:20
- Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
- Kontaktdaten:
Re: Button soll Schleife unterbrechen (möglichst ohne Thread
Ich kann dir nicht ganz folgen. Wo hast du PostEvent() genutzt? Kannst du den Code zeigen?
Re: Button soll Schleife unterbrechen (möglichst ohne Thread
Ja, kann ich gleich nochmal zurückschrauben.
Hier erstmal meine Variante ohne PostEvent, einfach mit einem eigenen Flag:
Hier erstmal meine Variante ohne PostEvent, einfach mit einem eigenen Flag:
Code: Alles auswählen
EnableExplicit
Define win, progress, bSearch, bCancel
Define quit
Define searching = #False
Define search = 0
Procedure startSearch()
Shared searching, search, bSearch, bCancel, progress
If Not searching
searching = #True
search = 0
DisableGadget(bSearch, 1)
DisableGadget(bCancel, 0)
SetGadgetState(progress, 0)
EndIf
EndProcedure
Procedure stopSearch()
Shared searching, search, bSearch, bCancel, progress
If searching
searching = #False
search = 0
DisableGadget(bCancel, 1)
DisableGadget(bSearch, 0)
SetGadgetState(progress, 0)
EndIf
EndProcedure
Procedure search()
Shared searching, search, bSearch, bCancel, progress
If searching
search + 1
Debug "searching " + search + " .."
SetGadgetState(progress, 100.0 * search / 20)
Delay(100)
If search >= 20
Debug "finished"
stopSearch()
EndIf
Else
Debug "cancel"
EndIf
If Not searching
search = 0
DisableGadget(bCancel, 1)
DisableGadget(bSearch, 0)
EndIf
EndProcedure
win = OpenWindow(#PB_Any, 100, 100, 420, 130,"window", #PB_Window_ScreenCentered)
AddKeyboardShortcut(win, #PB_Shortcut_Escape, 99)
progress = ProgressBarGadget(#PB_Any, 10, 10, 400, 30, 0, 100)
bSearch = ButtonGadget(#PB_Any, 10, 50, 400, 30, "suchen")
bCancel = ButtonGadget(#PB_Any, 10, 90, 400, 30, "abbrechen")
DisableGadget(bCancel, 1)
Repeat
While WaitWindowEvent(2)
If EventWindow() = win
If Event() = #PB_Event_Menu And EventMenu() = 99
quit = #True
ElseIf Event() = #PB_Event_CloseWindow
quit = #True
ElseIf Event() = #PB_Event_Gadget
If EventGadget() = bSearch
startSearch()
ElseIf EventGadget() = bCancel
stopSearch()
EndIf
EndIf
EndIf
Wend
If searching
search()
EndIf
Until quit
Re: Button soll Schleife unterbrechen (möglichst ohne Thread
Folgender Code sucht zwar nicht, aber der Such-Button wird disabled. Wenn ich aber das auskommentierte ;PostEvent(#eventSearch) aktiviere dann generiert die Suche immer wieder Search-Events und das disabled wird nicht sichtbar obwohl es vor dem erstem PostEvent stattfand.
<edit>
Mit gtk2 sieht man sogar wie der Such-Button hängenbleibt.
Code: Alles auswählen
EnableExplicit
Enumeration #PB_Event_FirstCustomValue
#eventSearch
EndEnumeration
Define win, progress, bSearch, bCancel
Define quit
Define searching = #False
Define search = 0
Procedure search()
Shared searching, search
Shared bSearch, bCancel
If searching
search + 1
Debug "searching " + search + " .."
Delay(100)
If search >= 20
Debug "finished"
searching = #False
Else
PostEvent(#eventSearch)
EndIf
Else
Debug "cancel"
EndIf
If Not searching
search = 0
DisableGadget(bCancel, 1)
DisableGadget(bSearch, 0)
EndIf
EndProcedure
win = OpenWindow(#PB_Any, 100, 100, 420, 130,"window", #PB_Window_ScreenCentered)
AddKeyboardShortcut(win, #PB_Shortcut_Escape, 99)
progress = ProgressBarGadget(#PB_Any, 10, 10, 400, 30, 0, 100)
bSearch = ButtonGadget(#PB_Any, 10, 50, 400, 30, "suchen")
bCancel = ButtonGadget(#PB_Any, 10, 90, 400, 30, "abbrechen")
DisableGadget(bCancel, 1)
Repeat
WaitWindowEvent()
If EventWindow() = win
If Event() = #PB_Event_Menu And EventMenu() = 99
quit = #True
ElseIf Event() = #PB_Event_CloseWindow
quit = #True
ElseIf Event() = #PB_Event_Gadget
If EventGadget() = bSearch
DisableGadget(bSearch, 1)
DisableGadget(bCancel, 0)
searching = #True
Debug "post"
;PostEvent(#eventSearch)
ElseIf EventGadget() = bCancel
DisableGadget(bCancel, 1)
DisableGadget(bSearch, 0)
searching = #False
PostEvent(#eventSearch)
EndIf
EndIf
ElseIf Event() = #eventSearch
Debug "seach event"
search()
EndIf
Until quit
Mit gtk2 sieht man sogar wie der Such-Button hängenbleibt.
- silbersurfer
- Beiträge: 174
- Registriert: 06.07.2014 12:21
Re: Button soll Schleife unterbrechen (möglichst ohne Thread
Ich finde es mit Threads doch schöner gerade wenn es um Suchen geht bei Verzeichnis durchsuchen geht ja auch immer viel Zeit ins Land
hier mal mein Ansatz dazu
hier mal mein Ansatz dazu
Code: Alles auswählen
EnableExplicit
Structure thread
Thread.i
stop.i
such.s
EndStructure
Define Startsuche,EventID,Quit,a, Mein.Thread
Dim suchfeld.s(1000000)
#Window=1
#suche=3
For a=0 To 1000000
suchfeld(a)="Text"+Str(a)
Next
Procedure Suchen(*this.Thread)
Shared suchfeld()
Protected a
Repeat
If a>1000000 : a=0 : EndIf
If *this\such =suchfeld(a)
Debug "es wurde was gefunden ! "
EndIf
If *this\stop=1
Break
EndIf
a=a+1
ForEver
EndProcedure
Procedure SucheStarten(suchen.s,*this.Thread)
With *this
\Thread=CreateThread(@Suchen(),*this)
\such=suchen
\stop=0
EndWith
EndProcedure
If OpenWindow(#Window, 0, 0, 400, 200, "Test Window",#PB_Window_ScreenCentered | #PB_Window_SystemMenu)
ButtonGadget(#Suche,10,10,100,25,"Suche starten")
EndIf
Repeat
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_CloseWindow
Quit=1
Case #PB_Event_Gadget
Select EventGadget()
Case #suche
If Startsuche=0
SetGadgetText(#Suche, "Suche anhalten")
Startsuche=1
SucheStarten("Text999999",Mein.Thread)
; Hier diverse Schleifen die irgendwelches Zeug erledigen...
ElseIf Startsuche=1
SetGadgetText(#Suche, "Suche Starten")
Startsuche=0 : Mein\stop=1
EndIf
EndSelect
EndSelect
Until Quit=1
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Re: Button soll Schleife unterbrechen (möglichst ohne Thread
Benötigt Modul 'ThreadToGUI'
Code: Alles auswählen
;-TOP
; Example ThreadToGUI
IncludeFile "Modul_ThreadToGUI.pb"
Enumeration #PB_Event_FirstCustomValue
#My_Event_ThreadToGUI
EndEnumeration
Structure udtThreadData
ThreadId.i
Cancel.i
; Data
EndStructure
Procedure thFillList(*data.udtThreadData)
Protected text.s, count
UseModule ThreadToGUI
DoSetGadgetText(1, "Stop Fill")
DoStatusBarText(0, 0, "Thread 1 running...")
For count = 1 To 120
text = FormatDate("%HH:%II:%SS - Number ", Date()) + Str(count)
DoAddGadgetItem(0, -1, text)
Delay(1000)
If *data\Cancel
Break
EndIf
Next
DoStatusBarText(0, 0, "Thread 1 finished.")
DoSetGadgetText(1, "Start Fill")
*data\Cancel = 0
UnuseModule ThreadToGUI
EndProcedure
Procedure thFlash(*data.udtThreadData)
Protected count, col
UseModule ThreadToGUI
DoSetGadgetText(2, "Stop Flash")
For count = 0 To 40
For col = 0 To 3
DoStatusBarProgress(0, 1, count * 20 + col * 5)
Select col
Case 0 : DoSetGadgetColor(3, #PB_Gadget_BackColor, RGB(255,0,0))
Case 1 : DoSetGadgetColor(3, #PB_Gadget_BackColor, RGB(255,255,0))
Case 2 : DoSetGadgetColor(3, #PB_Gadget_BackColor, RGB(0,255,0))
Case 3 : DoSetGadgetColor(3, #PB_Gadget_BackColor, RGB(255,255,255))
EndSelect
Delay(1000)
If *Data\Cancel
Break 2
EndIf
Next
Next
DoStatusBarProgress(0, 1, 100)
DoSetGadgetText(2, "Start Flash")
*data\Cancel = 0
UnuseModule ThreadToGUI
EndProcedure
Procedure Main()
Protected event, thread1.udtThreadData, thread2.udtThreadData
If OpenWindow(0, #PB_Ignore, #PB_Ignore, 800, 560, "Thread To GUI Example", #PB_Window_SystemMenu)
CreateStatusBar(0, WindowID(0))
AddStatusBarField(200)
StatusBarText(0, 0, "Thread 1")
AddStatusBarField(200)
AddStatusBarField(#PB_Ignore)
ListViewGadget(0, 0, 0, 800, 500)
ButtonGadget(1, 10, 510, 120, 24, "Start Fill")
ButtonGadget(2, 140, 510, 120, 24, "Start Flash")
StringGadget(3, 710, 510, 80, 24, "State", #PB_String_ReadOnly)
ThreadToGUI::BindEventGUI(#My_Event_ThreadToGUI)
Repeat
event = WaitWindowEvent(10)
Select event
Case #PB_Event_CloseWindow
If IsThread(thread1\ThreadId) Or IsThread(thread2\ThreadId)
MessageRequester("Info", "Threads running...")
Else
Break
EndIf
Case #PB_Event_Gadget
Select EventGadget()
Case 1
If Not IsThread(thread1\ThreadId)
thread1\ThreadId = CreateThread(@thFillList(), thread1)
Else
thread1\Cancel = 1
EndIf
Case 2
If Not IsThread(thread2\ThreadId)
thread2\ThreadId = CreateThread(@thFlash(), thread2)
Else
thread2\Cancel = 1
EndIf
EndSelect
EndSelect
ForEver
EndIf
EndProcedure : Main()
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive