Jump to content
Sign in to follow this  
tfabris

Help! Cannot exit my main form during a processing loop, using GUIOnEventMode.

Recommended Posts

tfabris

Can anyone tell me what I'm doing wrong here?

Run this program and notice that, you can close the application just fine if you close it before pressing the "Being Processing Now" button.

Then run it again, and notice that, you cannot close the application after pressing the "Begin Processing Now" button.

Is there a way to fix this?

; Example of problem I'm having with the GUI not closing.
; How do I fix this?
#include <GuiEdit.au3>
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1)
$MainForm = GUICreate("Test Application", 600, 400, 200, 200, BitOR($WS_MAXIMIZEBOX,$WS_MINIMIZEBOX,$WS_SIZEBOX,$WS_THICKFRAME,$WS_SYSMENU,$WS_CAPTION,$WS_OVERLAPPEDWINDOW,$WS_TILEDWINDOW,$WS_POPUP,$WS_POPUPWINDOW,$WS_GROUP,$WS_TABSTOP,$WS_BORDER,$WS_CLIPSIBLINGS))
GUISetOnEvent($GUI_EVENT_CLOSE, "MainFormClose")
$LogOutputTextBox = GUICtrlCreateEdit("", 8, 8, 580, 280, BitOR($ES_READONLY,$ES_WANTRETURN,$WS_HSCROLL,$WS_VSCROLL))
$GoButton = GUICtrlCreateButton("Begin Processing Now !", 8, 300, 237, 33, $WS_GROUP)
GUICtrlSetOnEvent($GoButton, "ProcessingLoop")
GUISetState(@SW_SHOW)
While 1
   ; Loop where the main application waits for user input.
   ; This works... If it reaches this and the user presses the main
   ; form close button, then the application closes just fine.
   Sleep (1000)
WEnd
Func MainFormClose ()
   ; This works fine, unless I'm in the processing loop.
   ; Why does this not work when I'm in the processing loop?
   MsgBox (0, "Closing", "You pressed the close button! Yay! Now exiting.")
   Exit
EndFunc
Func ProcessingLoop ()
   ; This loop simulates the main application processing loop.
   ; This is the part that I cannot exit. I'm putting sleeps in
   ; here like crazy. Why doesn't the Close Button event fire
   ; when I'm in this loop?
   For $x = 1 to 30
   ; If this were a real application, I would be doing something important here,
   ; like calculating the Question to the Ultimate Answer. But just for demo
   ; purposes, I'm going to just output some text.
   OutputText ("I am doing something. I have done something " & $x & " times now.")
   OutputText ("Boy I sure wish I could exit this application now.")
   OutputText ("Unfortunately, I must be task-killed now. WHY?!")
      Sleep (1000)
   Next
EndFunc
Func OutputText ($TextLine)
   ; Subroutine that makes it easy to output text to the edit control, for demonstration purposes.
   GuiCtrlSetData( $LogOutputTextBox, GuiCtrlRead ($LogOutputTextBox) & $TextLine & @CRLF)
   _GUICtrlEdit_LineScroll($LogOutputTextBox, 0, _GUICtrlEdit_GetLineCount($LogOutputTextBox))
EndFunc

Share this post


Link to post
Share on other sites
water

The AutoIt help file tells you:

"OnEvent Mode

In the OnEvent mode instead of constantly polling the GUI to find out if anything has happened you make the GUI temporarily pause your script and call a pre-defined function to handle the event. For example, if the user clicks Button1 the GUI halts your main script and calls a previously defined user function that deals with Button1. When the function call is completed the main script is resumed."

Therefore: As long as function ProcessingLoop is running the script doesn't check for any other GUI events.

Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2018-06-01 - Version 1.4.9.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-01-27 - Version 1.3.3.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites
tfabris

Thanks for that explanation, Water! I have crafted a solution based on your explanation, thank you!

I discovered that I could process GUI events in the middle of other functions just fine, so the explanation didn't make sense to me at first. I had to poke at things a bit to figure out exactly what it meant. I think a more accurate description, better than what is says in the Help, would be something like:

"If the GUI fires off one of its event handlers for one of its controls, it won't process any more GUI events until that particular event handler returns."

In other words, the problem isn't just that you can't call out to any functions at all, which is what I initially interpreted the explanation to mean. No, the problem is that you can't do a bunch of code (or sub-call out to a bunch of code) directly from the GUI event handler. If you do, then it won't ever return and the GUI never processes any other events. (I guess the GUI is single threaded or something?)

Anyway, with that knowledge, I was able to come up with a perfect solution that doesn't require rewriting the whole thing in Message-Loop mode. Instead of trying to call my main processing function from the button code, the button code sets a flag. That flag is then read by the main program loop and then fired off from within the main program loop. *THAT* works fine and I can terminate the program easily wherever I want now, even if the processing loop takes hours.

Pseudo code of my solution looks something like this:

; -------------
; BAD (ORIGINAL) CODE

; -------------
    GUICreate("Test Application")
    GUICtrlSetOnEvent($GoButton, "ProcessingLoop")

    While 1 
         Sleep(1000)
    Wend

    Func ProcessingLoop()
          ;Do lotsa stuff
    End Func



; -------------
; GOOD (MY SOLUTION) CODE

; -------------

    Global $GoFlag = 0


    GUICreate("Test Application")
    GUICtrlSetOnEvent($GoButton, "SetGoFlag")

    While 1 
         Sleep(1000)
         If $GoFlag == 1 Then
                ProcessingLoop()
                $GoFlag = 0
         EndIf
    Wend

    Func SetGoFlag()
           $GoFlag = 1
    End Func

    Func ProcessingLoop()
          ;Do lotsa stuff
    End Func

Share this post


Link to post
Share on other sites
Melba23

tfabris,

Take a look at the Interrupting a running function tutorial in the Wiki - shows the various ways you can do it in AutoIt. ;)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
tfabris

Take a look at the Interrupting a running function tutorial in the Wiki - shows the various ways you can do it in AutoIt. ;)

Yup, one of the methods shown in that Wiki entry was the one I ended up coming up with on my own. Thanks!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×