Sign in to follow this  
Followers 0
jmoskie

Threading for GUIs?

4 posts in this topic

Hello,

I'm working on an AutoIt application that does a lot of text comparisons in the background, and also has a GUI.

I've gone with an event-based GUI approach, because I figured it fit in better with the design of the application.

The flow of the application is this:

User loads application, there is one text box and one button (simple!).

There's a "While 1" loop that uses GUIGetMsg() to get events as they happen.

User fills in the text box, and clicks in the button. This sets a flag, $active, to true in my application.

Now, since $active is true, inside that same "While 1" loop, I make a call to parseText(), which is my primary parsing method.

The parsing is fairly intense, relatively, and can take up to two or three seconds to complete, which is fine for my purposes.

The problem is that the parsing and GUI display / events are all in the same thread. While the parsing is going on, I cannot click the button (to toggle $active to off), and I cannot drag the window around without substantial delay.

As a Java/C++ developer, I want to just spawn a second thread for the parser work, but I can't find an easy way to do that in AutoIt.

How can I separate these two functions to remove the choppiness from my application?

Share this post


Link to post
Share on other sites



...

I've gone with an event-based GUI approach, because I figured it fit in better with the design of the application.

...

There's a "While 1" loop that uses GUIGetMsg() to get events as they happen.

...

If you read the remarks of GUISetOnEvent you'll notice that when using GUIOnEventMode(1), GUIGetMsg is not used at all. You can change this While...WEnd loop to a simple one without trying to poll messages using GUIGetMsg and do the main processing there. Threading in AutoIt is not possible, as stated. You can search the examples forum but you won't be able to make a second thread with simple AutoIt instructions. You'll need to write the opcodes and get the functions pointers, or manage anything in a low-level. Unless you can come with a better implementation, threading is not required.

Share this post


Link to post
Share on other sites

Thanks Auth, I've removed the polling in the loop and it's still working fine.

However, the issue is still there. The UI drawing / interactions are still in the same thread as my parsing.

If I try to click a button in the UI, it has to wait for the parsing to finish before it can register the press. If I drag and hold the window, the parsing won't start again until I let go of the window.

I get that threading is difficult / hard, but is there any other way to ensure a "snappy" GUI response? Is there a way to fun a function in the "background" like the InetGet function, or is that just calling threading by another name?

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Thanks Auth, I've removed the polling in the loop and it's still working fine.

However, the issue is still there. The UI drawing / interactions are still in the same thread as my parsing.

If I try to click a button in the UI, it has to wait for the parsing to finish before it can register the press. If I drag and hold the window, the parsing won't start again until I let go of the window.

I get that threading is difficult / hard, but is there any other way to ensure a "snappy" GUI response? Is there a way to fun a function in the "background" like the InetGet function, or is that just calling threading by another name?

Without your code to see I am just guessing, but this sounds like a common problem that can often be solved with a simple solution, though I have offered this in the past and been wrong.

If your lengthy routine is in a function which is called directly by an event, that is to say if the function has been registered for an event using GuiCtrlSetOnEvent then the approach below might help.

When a function is called from an event, then the main script is interrupted and the function is executed. Usually the main script is just executing an idle loop but it could be doing anything. Once the function is called by the event then that function will be executed, the main scriopt is suspended and any further intereupts (events) are queued waiting for the function to finish. So you see the problem you have.

Say this is how your script looks

While 1
 sleep(90)
Wend

Func LongFunc()
blah
blah
..
endfunc

All you have to do is to change it like this

Global $startLongFunc=False
While 1
 sleep(90)
 if $startlongFunc then
 LongFuncB()
    $startlongFunc = False
 endif

Wend

Func LongFunc();<-------------this can't be interrupted by events so make it short
 $startlongFunc = true
endfunc

Func LongFuncB();<_----------this can now be interrupted by events
blah
blah
..
endfunc

Be aware that if you try this with more than one OnEvent function you are liable to get back into the same problem.

Having th eparsing halt while you drag a window is not fixed by this but I think that is more difficult and maybe not so important.

EDIT: typos

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

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  
Followers 0