Sign in to follow this  
Followers 0
NerdFencer

Multi-Thread UDF

12 posts in this topic

Here is a simple UDF and example script for multi-threading AutoIt applications from the same executable.

You must compile scripts using this to test or the alternate threads will not launch

UDF: Thread.au3

#include-once
#include "Example.au3" ; Change this for your own use

Global Const $Thread_RegRootKey = "HKLM\SYSTEM\CurrentControlSet\Control\AuThread\"
Global Const $Thread_MsgKill = "_THREAD_COMMAND_KILL_SLAVE"
Global $Thread_ProcessMessagesCallback, $Thread_Master

; Thread Creation
Func _Thread_Create($callback)
    Local $instances = ProcessList()
    ShellExecute(@ScriptFullPath,"/ThreadSpawn "&@AutoItPID&" "&$callback)
    Local $new = ProcessList()
    Local $used = False, $PID=-1
    For $i=1 To $new[0][0]
        $used = False
        For $j=1 To $instances[0][0]
            If $new[$i][1]==$instances[$j][1] Then
                $used=True
                ExitLoop
            EndIf
        Next
        If $used == False Then
            $PID = $new[$i][1]
        EndIf
    Next
    _Thread_SendCommand($PID,"Initialize")
    Return $PID
EndFunc

; Core Thread Operations
Func _Thread_GetFree($PID)
    Local $cmd = RegRead($Thread_RegRootKey&$PID,"Command")
    If @error Or $cmd=="" Then Return True
    Return False
EndFunc

Func _Thread_Slave()
    RegWrite($Thread_RegRootKey)
    RegWrite($Thread_RegRootKey&@AutoItPID)
    OnAutoItExitRegister("_Thread_End")
    If UBound($CmdLine)>=4 And $CmdLine[1]=="/ThreadSpawn" Then
        $Thread_Master = $CmdLine[2]
        $Thread_ProcessMessagesCallback = $CmdLine[3]
        _Thread_SlaveLoop()
        RegDelete($Thread_RegRootKey&@AutoItPID)
        Return
    EndIf
    RegWrite($Thread_RegRootKey&@AutoItPID,"Active","REG_DWORD",1)
EndFunc

Func _Thread_SendCommand($PID,$command)
    While _Thread_GetFree($PID)==False
        Sleep(15)
    WEnd
    RegWrite($Thread_RegRootKey&$PID,"Command","REG_SZ",$command)
    If Not(@error) Then Return True
    Return False
EndFunc

Func _Thread_End()
    RegDelete($Thread_RegRootKey)
EndFunc

Func _Thread_EndSlave($SlavePID)
    RegWrite($Thread_RegRootKey&$SlavePID,"Tmsg","REG_SZ",$Thread_MsgKill)
EndFunc

Func _Thread_SlaveLoop()
    Execute($Thread_ProcessMessagesCallback&"()")
    RegDelete($Thread_RegRootKey&@AutoItPID)
    Exit
EndFunc

; Variable and Command Sharing
Func _Thread_Post($var,$data)
    RegWrite($Thread_RegRootKey&@AutoItPID,$var,"REG_SZ",$data)
EndFunc

Func _Thread_Read($PID,$var)
    Return RegRead($Thread_RegRootKey&$PID,$var)
EndFunc

Func _Thread_CheckCommand()
    Local $command = RegRead($Thread_RegRootKey&@AutoItPID,"Command")
    RegDelete($Thread_RegRootKey&@AutoItPID,"Command")
    Return $command
EndFunc

Func _Thread_CheckKill()
    If RegRead($Thread_RegRootKey&@AutoItPID,"Tmsg")==$Thread_MsgKill Then Return True
    If RegRead($Thread_RegRootKey&$CmdLine[2],"Active")==1 Then Return False
    Return True
EndFunc

Example: Example.au3

; Important to use include-once
#include-once
; In Thread.au3, you must include your own source files that contain your slave thread event processor
#include "Thread.au3"


_Thread_Slave() ; Must be called at the beginning of every script if this is the alt thread, this is where it breaks off from the standard execution
; Create a thread using ProcessThreadMessages as the initial function for our alt thread. This can be done with as many threads as you want
$thread = _Thread_Create("ProcessThreadMessages")

; Hide the slave thread's window
_Thread_Post("Message","This window will soon dissapear")
_Thread_SendCommand($thread,"Set")
MsgBox(0,"Master","Hiding Slave")
_Thread_SendCommand($thread,"Hide")

; Show the slave thread's window
_Thread_Post("Message","This window is now visible")
_Thread_SendCommand($thread,"Set")
MsgBox(0,"Master","Showing Slave")
_Thread_SendCommand($thread,"Show")

; Pause before quitting
MsgBox(0,"Master",$thread)
; This is the end of execution, and all other running threads will automatically be sent the message to kill themselves

; Process events for the slave thread
Func ProcessThreadMessages()
    Local $msg,$tGUI,$tLab
    While Not(_Thread_CheckKill()) ; Check and see if the master wants us dead or not
        ; Check for commands from the amster thread
        $msg = _Thread_CheckCommand()
        Switch $msg
            Case "Initialize"
                ; Initial command always sent by the thread creator
                $tGUI = GUICreate(@AutoItPID,Default,Default,0,0)
                $tLab = GUICtrlCreateLabel("This Control Has not been Set Yet",5,5)
                GUISetState(@SW_SHOW,$tGUI)
            Case "Hide"
                GUISetState(@SW_HIDE,$tGUI)
            Case "Show"
                GUISetState(@SW_SHOW,$tGUI)
            Case "Set"
                ; Retrives the Message variable posted by the master thread
                GUICtrlSetData($tLab,_Thread_Read($Thread_Master,"Message"))
        EndSwitch
        ; Check for GUI Events
        $msg = GUIGetMsg()
        Switch $msg
            Case -3
                Exit
        EndSwitch
        Sleep(15)
    WEnd
EndFunc

Enjoy :D


_________[u]UDFs[/u]_________-Mouse UDF-Math UDF-Misc Constants-Uninstaller Shell

Share this post


Link to post
Share on other sites



Is the registry the only way to share data? That seems like it could be bad, for some reason, but maybe I just have an unreasoning distrust of all things registry. Very cool, otherwise.

AutoIt is getting some very mature packages this year... another decent threading implementation and real object orientation. GJ, NerdFencer :D

Share this post


Link to post
Share on other sites

Looks interesting but I don't think your actually creating multiple threads. It looks like your creating other processes and then sending them messages.

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Thanks for the feedback everybody :D

Is the registry the only way to share data? That seems like it could be bad, for some reason, but maybe I just have an unreasoning distrust of all things registry. Very cool, otherwise.

AutoIt is getting some very mature packages this year... another decent threading implementation and real object orientation. GJ, NerdFencer :huggles:

There are better ways using a more complex windows API subset with semaphores etc, but I haven't figured all of this out yet, so I am using the registry as a temporary medium. In some future version, I will eliminate the dependency on the registry.

Thanks JRowe : I will hopefully be releasing a better implementation soon.

Looks interesting but I don't think your actually creating multiple threads. It looks like your creating other processes and then sending them messages.

In essence, thats all threading really is, but it usually entails a more closely shared memory space (which I am working on figuring out). Edited by NerdFencer

_________[u]UDFs[/u]_________-Mouse UDF-Math UDF-Misc Constants-Uninstaller Shell

Share this post


Link to post
Share on other sites

Very interesting code. Even though its not "true threading" I can see this being useful.

In essence, thats all threading really is, but it usually entails a more closely shared memory space (which I am working on figuring out).

If I were you I'd be careful about trying to make it one thread. AutoIt is not "thread-safe" so all types of errors are bound to occur.


HKTunes:Softpedia | GoogleCodeLyricToy:Softpedia | GoogleCodeRCTunes:Softpedia | GoogleCodeMichtaToolsProgrammer n. - An ingenious device that turns caffeine into code.

Share this post


Link to post
Share on other sites

You could use mailhost instead of registry for communication.


[Not using this account any more. Using "iShafayet" instead]

Share this post


Link to post
Share on other sites

You could use mailhost instead of registry for communication.


[Not using this account any more. Using "iShafayet" instead]

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

Very nice!! I already have a use for this, for a sub-process that's hogging my main process.

Thanks for sharing.

You could use mailhost instead of registry for communication.

I agree, I use the MailSlot UDF a lot for communicating between scripts, and

I must say it's great, and simple to use. Plus bonus is it works easily across

a network.

Edited by dmob

Share this post


Link to post
Share on other sites

Any progress?

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

Posted 05 February 2010 - 05:46 AM

And NO, AutoIt does not support actual Multi-Threading.

Edited by D4RKON3

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