Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

real thread handling


  • Please log in to reply
28 replies to this topic
buergi
  • Members
  • 2 posts
  • Last active: May 06 2007 11:57 PM
  • Joined: 12 Apr 2007
Hi,
there is only one feature that i miss in the great AHK!
a real thread handling, like running functions in new threads, syncing of multiple threads, wait on threads etc.
I've tried to fake the feature by DllCall but i cannot get it working.
just as an example: here is a short kind of tutorial from MS for creating threads by using the Win API in C.

if there is a way to fake threads please tell my, i didn't found one.
i can't find a way to pass a function pointer to the CreateThread api function.

this feature would be really really useful, especially on multi-core cpus
it allows you to parallelize cpu intensive functions, or just thing on downloading multiple files at the same time.

so if there is a way to achieve thread handling please tell me, if not please think about including these features in the next release, would be great and would make AHK even more powerful

thx4reading
buergi

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
While I agree it would be a powerful feature, I see it as a bit too advanced for the general audience of AHK (lot of non-programmer which already struggle to get SetTimer working) or even for the general purpose of AHK (Windows automation).
Thread programming is known to be tricky and quite complex: after running tasks in parallels, people will ask ways to synchronize threads, to share data between threads, and so on. A real Pandora box! :-)
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

buergi
  • Members
  • 2 posts
  • Last active: May 06 2007 11:57 PM
  • Joined: 12 Apr 2007
I know that it's complex but i think some basic features would be better that nothing. just run a function in a new thread, and wait for thread to be finished, and wait for all threads to be finished. that would be kind of basic threat functions, which would be very useful and nevertheless easy to use.

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004

While I agree it would be a powerful feature, I see it as a bit too advanced for the general audience of AHK (lot of non-programmer which already struggle to get SetTimer working) or even for the general purpose of AHK (Windows automation).

Bah... :p

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005

Bah... :p

Despite I often use it as such, I don't see AutoHotkey as a general purpose language, that should have full thread support, general socket support, classes, and what's not. While these are nice features, adding everything and the kitchen sink would bloat the language, resulting perhaps in multi-megabytes of download, like for Python or Perl.
Plus it would be a maintenance nightmare for Chris...
Now, that's just my vision of the language, even not as extreme as jonny's... ;-)

Now, perhaps a simple support of worker threads can be simple to implement, although I guess it can bring lot of problems and bugs (concurrent access to data and such).
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

majkinetor
  • Moderators
  • 4512 posts
  • Last active: Today, 07:41 AM
  • Joined: 24 May 2006

While I agree it would be a powerful feature, I see it as a bit too advanced for the general audience of AHK (lot of non-programmer which already struggle to get SetTimer working) or even for the general purpose of AHK (Windows automation).

Bah 2.

Despite I often use it as such, I don't see AutoHotkey as a general purpose language, that should have full thread support, general socket support, classes, and what's not. While these are nice features, adding everything and the kitchen sink would bloat the language, resulting perhaps in multi-megabytes of download, like for Python or Perl.

Ahh, a preacher that doesn't beleive in God ?
BTW, your assumptation about multimegabytes and kitchen sink's are higly opiniated, and can not acctually be supproted in reality. You should join jonny in his mission to destroy AHK. :lol:

Plus it would be a maintenance nightmare for Chris...

LOL.
The point of constructing the mean of AHK extending is just the oposite.
When, people ?
When will you learn that non-extensible thing will die.
After several years of AHK devel, what zero new developers can tell you ? Even with this popularty no programmer can find time to involve itself in understanding of AHK architecture just to be able to add one parameter to some command after few months. Chris should make it extensible, so others, knowing some convineint SDK can extend it, and it should be able to latter include those extensions natively if they are good. Also, its a matter of time when will Chris be tired of such a big responsibility. Most suggestions I was tellin' here were to remove burden of hard work on wishes from Chris's back and to redirect it to community members that are willing to evolve AHK. I know I will never create again something like MMenu module. It took me lot of research to deal with AHK quirks, and it still isn't perfect due to the AHK limitations. So, it really doesn't motivate even motivated ppl to work for commuinity, no wonder why many power members left the scene - I guess they became tired.
AHK is doomed if it continues this way. I guarantie.

About threads
The single, most needed, most wanted of all missing ahk features (although many ppl are not aware of that), and things goes beyond ahk, I don't remember I saw any scripting language in the AHK class that can do threading. I already have 20 scripts I would like to run all the time, but I can't , even using merging technique as timers are nasty beasts to handle with.

The 1 AHK instance, running multiple scirpts in their own treads is a dream come true. I would sacrifice anything else - v2.0, arrays, and thing that anybody can think of on this planet - just to see AHK supports this. Its absense so lowers its functionality and so lowers its usage, and that is something I hear every day. Everytime I said to somebody AHK is cool, after some time when that one discovers that each script starts another AHK instance, it flee away.

So, yeah, AHK should be redesigned from ground-top to support multithreading. Colosal task, if not designed from the start (Chris once said, though, that he was thinking about that from the start, although I don't know how that reflects to current AHK architecthure) but worth every second, day, year...
Posted Image

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005

BTW, your assumptation about multimegabytes and kitchen sink's are higly opiniated, and can not acctually be supproted in reality.

No, I mention two language whose archives weight over 9MB, that's a fact, not an opinion. Now, most of this weight come from the standard library, which indeed has a kitchen sink (or close...), but it counts.
I think you would be the first one to scream if AHK would be bloated...

When will you learn that non-extensible thing will die.

Well, it seems quite alive and well to me... This language fills a niche, and does it well.
I find it perfect for small to medium projects, quickly written programs, fast GUI construction, and of course Windows automation in general. But for a major project, with complex data structures, elaborate GUI and such, I would choose another language.
Chris is slowly improving it, but basically it was an ad hoc language for a given purpose.
Now, I would worry more about Vista going the same way as other frameworks (Java's Swing, Mozilla programs, GTK+ applications, Rebol ones, etc.), ie. not responding to standard Windows API so making AHK more and more unusable.

Everytime I said to somebody AHK is cool, after some time when that one discovers that each script starts another AHK instance, it flee away.

Really? Surprising... AHK is lightweight, so having several instances isn't such a problem.

Note I don't discard your proposals, making AHK more flexible, extensible and such is a good goal and shouldn't make it much more heavy.
I just hope it will never become a Java, taking several dozen of seconds to start a program because of JVM overhead (and eating multimegabytes of memory)...
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

majkinetor
  • Moderators
  • 4512 posts
  • Last active: Today, 07:41 AM
  • Joined: 24 May 2006

I think you would be the first one to scream if AHK would be bloated...

Correct. Things can be done the good way and the bad way.

Well, it seems quite alive and well to me...

They all do, in the beginning...

This language fills a niche, and does it well.I find it perfect for small to medium projects, quickly written programs, fast GUI construction, and of course Windows automation in general. But for a major project, with complex data structures, elaborate GUI and such, I would choose another language.

The language is not such a big problem although it is definitely low on the sophistication list. There are too problems: language sophistication and language extensibility. While first is at pretty low level, other is completely absent.

AHK is lightweight, so having several instances isn't such a problem.

Really ? what machine do you have ? I have 6GHz here with 2GB RAM and I can notice performance drawback when I start 5 AHK instances, more-over, you wont use AHK alone on the blank machine, but with one running SQL Serviers, World of Warcraft, Visual Studios, Delphis, AutoCads etc... Typical error among programming world, they think programs will run in vacuum.
BTW, I am not talking about several instances. Once you start to like AHK u want some of its resident scripts, like Expose, ISense, Favmenu, Monster, GMail Tray Checker, Notes, CPULoad, Bandwith meter etc... running all the time. I already have around 10 scripts that should be resident and I merged few of them already so to avoid ahk instances for smaller scripts. I heard first time for AHK before a year. If this is what I get in year, you can extrapolate how things will look after some time...



Now, I would worry more about Vista going the same way as other frameworks (Java's Swing, Mozilla programs, GTK+ applications, Rebol ones, etc.), ie. not responding to standard Windows API so making AHK more and more unusable.

Nothing that can't be fixed with proper plugin design.

Note I don't discard your proposals, making AHK more flexible, extensible and such is a good goal and shouldn't make it much more heavy.
I just hope it will never become a Java, taking several dozen of seconds to start a program because of JVM overhead (and eating multimegabytes of memory)...

Note that you have funny way to express your support. You first say everything against it, then do it again, and again, and then you say you support it in one small paragraph after everything... The right way is to say that you support it, then do your comments about how it should look like. Not discard in advance because you think it might get badly implemented. I don't like Java, I don't like dotNet. They are superb as frameworks, but I think this tehcnology is to abstract for this time. All dotNet applications perform as sht here. The same with Java. That is technology for some other computers or for ppl who like to have slow responding, resource hungry programs, freaks so to say. I can understand one likes to programm in those, as I really think C# is one of the best things around and I enjoy programming it very much. However, I would never use it to create anything that should be responsive and performant now. I think that AU3 is going in direction you expressed. Even the basic hello script that I tried runs considerably slower then AHK equivalent. I beleive that Chris is excellent programmer and designer. I also beleive that excllent programmers can take a wrong path and I just can't stand around and screem "Yeah, its all good, Chris did it, it must be good. Its his toy, love it or leave it". I beleive that man who did so much for us at least deserved to be honest with him, at least if you are in the same passionate group of people like he is.
Posted Image

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005
The following code has relevance to the ask-for-help topic Changing button text where a functionality to kill a running thread is required!

Gui +ToolWindow
Gui, Add, Button, w100 h25 gStartStop vButtonText, Start
Gui, Add, StatusBar
Gui, Show, , Test
CBA_Count := RegisterCallback( "Count" )
Return

StartStop:
GuiControlGet, ButtonText
If ( ButtonText = "Start" ) 
   {
     GuiControl,, ButtonText, Stop
     SetTimer, Start, -1
   }
Else
   {
     GuiControl,, ButtonText, Start
     SetTimer, Stop, -1
   }
   
Return


[color=red]Count() {
Loop {
         Count ++ 
         SB_SetText( "`t" Count )
         Sleep 250
     }
}[/color]

Start:
 Thread := DllCall( "CreateThread", UInt,0, UInt,0, UInt,CBA_Count, UInt,0, UInt,0, UInt,0 )
Return

Stop:
 DllCall( "TerminateThread", UInt,Thread, UInt,0 )
 DllCall( "CloseHandle", UInt,Thread ) 
Return

GuiClose:
 ExitApp

The problem with the above code is that the loop performs only a single iteration and appears to have exited the thread!

I am able to see from Process Monitor v1.12 that the thread is being successfully created and terminated .. but the loop does not perform for infinite count.

Posted Image

If I replace the Loop with a MsgBox, the Start/Stop button Creates / Terminates the MsgBox successfully!

Am I missing something? Can Multi threading be simulated at all with current AHK version ?

:roll:

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

if there is a way to fake threads please tell my, i didn't found one.
i can't find a way to pass a function pointer to the CreateThread api function.

this feature would be really really useful, especially on multi-core cpus
it allows you to parallelize cpu intensive functions, or just thing on downloading multiple files at the same time.


The following seems to work for me:

Gui -Sysmenu
CBA_DL1 := RegisterCallback( "DL1" )
CBA_DL2 := RegisterCallback( "DL2" )
CBA_DL3 := RegisterCallback( "DL3" )

DllCall( "CreateThread", UInt,0, UInt,0, UInt,CBA_DL1, UInt,0, UInt,0, UInt,0 )
DllCall( "CreateThread", UInt,0, UInt,0, UInt,CBA_DL2, UInt,0, UInt,0, UInt,0 )
DllCall( "CreateThread", UInt,0, UInt,0, UInt,CBA_DL3, UInt,0, UInt,0, UInt,0 )

Gui, Add, Text, w100 h25 +Border +0x201 vTimer
Gui, Show,, Timer
SetTimer, Timer, 750


DL1() { ; v1.0.47.01
URLDownloadToFile, https://ahknet.autohotkey.com/programs/AutoHotkey104701_Install.exe
                 , AutoHotkey104701_Install.exe
Return
}

DL2() { ; v1.0.46.17
URLDownloadToFile, https://ahknet.autohotkey.com/programs/AutoHotkey104617_Install.exe
                 , AutoHotkey104617_Install.exe
Return
}

DL3() { ; v1.0.45.04
URLDownloadToFile, https://ahknet.autohotkey.com/programs/AutoHotkey104504_Install.exe
                 , AutoHotkey104504_Install.exe
Return
}

Timer:
 FormatTime, Time, , HH:mm:ss
 GuiControl,, Timer, %Time%
Return

Right-click-menu of the Tray Icon suspends the Timer but not the URL Downloads .. Does it mean that the above code is multi threaded ?

:?: :roll:

daniel2
  • Guests
  • Last active:
  • Joined: --
Skan-- This is a really cool discovery! In a recent discussion about using loops in separate threads.. it led me to experimenting w/ your examples.. & I am running into issues.
#Persistent
CBA_FirstLoop := RegisterCallback( "FirstLoop" )
CBA_SecondLoop := RegisterCallback( "SecondLoop" )
DllCall( "CreateThread", UInt,0, UInt,0, UInt,CBA_FirstLoop, UInt,0, UInt,0, UInt,0 )
DllCall( "CreateThread", UInt,0, UInt,0, UInt,CBA_SecondLoop, UInt,0, UInt,0, UInt,0 )
return

FirstLoop() {
  X := 0
  Loop  {
     X += 1
     ToolTip, X = %X%, 10, 20, 1
     Sleep 100
  }
}

SecondLoop()  {
  Y := 1
  Loop  {
     Y *= 2
     ToolTip Y = %Y%, 10, 40, 2
     Sleep 100
  }
}
It seems to launch both tooltips.. but somehow both the loops are still conflicting :?
Just curious if you have any thoughts...
Once again-- nice find! I already have a number of things I plan to experiment w/ that were previously unattainable using a single ahk script.. :D

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004
Interesting... Look, over there coming through the cracks, bugs :!:
[mumble]where did that spray go again...[/mumble]

Just kidding :p :lol: (I hope...)

tonne
  • Members
  • 1654 posts
  • Last active: May 06 2014 06:22 PM
  • Joined: 06 Jun 2006
From the manual on threads:

Although AutoHotkey doesn't actually use multiple threads, it simulates that behavior: If a second thread is started -- such as by pressing another hotkey while the previous is still running -- the current thread will be interrupted (temporarily halted) to allow the new thread to become current. If third thread is started while the second is still running, both the second and first will be in a dormant state, and so on.

When the current thread finishes, the one most recently interrupted will be resumed, and so on, until all the threads finally finish. When resumed, a thread's settings for things such as ErrorLevel and SendMode are automatically restored to what they were just prior to its interruption; in other words, a thread will experience no side-effects from having been interrupted (except for a possible change in the active window).


I other words the ahkkernel isn't prepared for true multithreading and all sorts of sideeffects are likely to occur.

On my computer your simple example seems to mess the tooltip text (or position) up, sometimes the wrong value is shown.

daniel2
  • Guests
  • Last active:
  • Joined: --

From the manual on threads

Yes- I understand how threads are normally handled in ahk-- but Skan was attempting at overcoming them w/ his use of dllcall....
The link from my above post-- I mention that not only does one thread interupt the other-- it then prevents future threads from being launched! Skan's method here does overcome that at least....

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

Skan-- This is a really cool discovery! In a recent discussion about using loops in separate threads.. it led me to experimenting w/ your examples.. & I am running into issues.


I am having the same problem when I tried to modify my much similar code : Controlling one script from another script

But I have to admit that I am much happier with the limited facility.
For my current project, one particular DllCall() goes into a wait state and during the wait, the GUI cannot process a single message ( Cannot move or minimise ) ... I cannot exit the script with a hotkey bound to ExitApp command. Everything gets buffered until the wait is over. Not even a right click on Tray Icon worked. I had to kill the process from task-manager if the wait condition was never satisfied.

SetTimer would/did not work as I found both auto-execute section as well as the sub-routine shared the same Thread.

I had to compromise with our infamous workaround of using two scripts. One script waits for the condition and alerts the other script which updates its GUI. Again, the second script could never close the first script in a gentler way .. had to kill the process :(

CreateThread() seems to have solved the above problem. The main thread seems to work comfortably when the Dll function is called as a seperate Thread.

I just discovered this method is limited to three threads per script:

CBA_Thread1 := RegisterCallback( "Thread1" )
CBA_Thread2 := RegisterCallback( "Thread2" )
CBA_Thread3 := RegisterCallback( "Thread3" )

DllCall( "CreateThread", UInt,0, UInt,0, UInt,CBA_Thread1, UInt,0, UInt,0, UInt,0 )
DllCall( "CreateThread", UInt,0, UInt,0, UInt,CBA_Thread2, UInt,0, UInt,0, UInt,0 )
DllCall( "CreateThread", UInt,0, UInt,0, UInt,CBA_Thread3, UInt,0, UInt,0, UInt,0 )

; Main Thread .. 
ThreadID := DllCall( "GetCurrentThreadId") ; SetTimer started label will also use this ID
hThread  := DllCall( "OpenThread", UInt,0x1F03FF, UInt,0, UInt,ThreadID )
MsgBox, 0, Main Thread, ThreadID : %hThread%

Return

; Note 1 ;  THREAD_ALL_ACCESS := 0x1F03FF
; Note 2 ;  AHK terminates all the threads when Script exits.
; Note 3 ;  AHK crashes if 4th Thread creation is attempted.

Thread1() { 
 ThreadID := DllCall( "GetCurrentThreadId")
 hThread  := DllCall( "OpenThread", UInt,0x1F03FF, UInt,0, UInt,ThreadID )
 MsgBox, 0, Thread 1, ThreadID : %hThread%
Return
}

Thread2() { 
 ThreadID := DllCall( "GetCurrentThreadId")
 hThread  := DllCall( "OpenThread", UInt,0x1F03FF, UInt,0, UInt,ThreadID )
 MsgBox, 0, Thread 2, ThreadID : %hThread%
Return
}

Thread3() { 
 ThreadID := DllCall( "GetCurrentThreadId")
 hThread  := DllCall( "OpenThread", UInt,0x1F03FF, UInt,0, UInt,ThreadID )
 MsgBox, 0, Thread 3, ThreadID : %hThread%
Return
}

Note: Close the MsgBox titled Main Thread as last one. MsgBoxes are overlapped .. move them to comfortable positions.

:)

PS: It would be nice if Mr.Chris could give us some explanations.