Jump to content

This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies. Find out more here. X
X


Photo

Threaded Dll Sample


  • Please log in to reply
17 replies to this topic

#1 Uten

Uten

    stupid is as stupid does..

  • Active Members
  • PipPipPipPipPipPip
  • 1,989 posts

Posted 02 May 2006 - 04:19 AM

Multi threaded dll created in freebasic.

From time to time people as for multi threading in AutoIt. Although I think it would be cool to have the ability of launching code in a new thread I do not think it will happens before someone steps up and are prepared to practically create a new AutoIt code base. I say this because I have read what better informed people than me are saying about the subject.

Anyhow, you have this killer idea whom really needs to be done asynchronously what do you do? You write it in C/C++, VB or you can, do it as done in this sample, write it in freebasic.

Why would you do it in two languages rather than one. Probably because AutoIt is pretty nice for what it does best, act as the glue between your code and windows applications. You maybe have experience in creating simple GUI's in AutoIt. And the fileinstall function is probably the simplest way you can have your small utilities wrapped up in one exe. No install hazel.

Enough said. Her is a sample multithreaded dll written in freebasic version 0.15. The sample consist of 4 files.
1: The dll code
2: A dll interface definition to be used with freebasic applications.
3: A freebasic test application.
4: A AutoIt v3 Beta 118 application

You will also find all files, including compiled dll and freebasic test app, in a attached zip file at the bottom of this post.

The dll: thdll.bas
Plain Text         
' FILENAME: thdll.bas ' COMPILE: fbc -dll thdll.bas ' PURPOSE: Demonstrate a multithreaded dll created with freebasic ' Include is not suposed to be used when we compile as dll ??? #include once "thdll.bi" dim shared gState as integer          ' Status reflecting the job done in the thread dim shared gRun as integer          ' Flag telling the thread to run or quit dim shared gCalls as integer          ' Counting call's to this api dim gTH as integer                  ' Thread handel ID dim gMutexID as integer            ' mutex id to be used when shared variables are updated. ' ' PURPOSE: Test calling conventions from application function AddNumbers CDECL(byval operand1 as integer, byval operand2 as integer) as integer export     Return  (operand1 + operand2) end function ' ' PURPOSE: Function to run in seperate tread. SUB mythread CDECL ( byval mutexID as integer )     ' Do some realy lengthy woork     While gRun = 1         mutexlock(mutexID)          ' Use mutex to lock memmory before update             gState = gState + 1         mutexunlock(mutexID)         'print "gState:="; gState         Sleep(1000)     Wend END SUB ' ' PURPOSE: Start a thread FUNCTION Startit CDECL () AS INTEGER export     gState = 0     gCalls +=1     gRun = 1     gMutexID = mutexcreate()     gTH=threadcreate(@mythread, gMutexID)     dim ret as integer     ret = gTH     Startit = ret END FUNCTION ' ' PURPOSE: Stop the thread FUNCTION Stopit CDECL () AS INTEGER export     gCalls +=1     gRun = 0     if gTH <> 0 Then         threadwait(gTH)         mutexdestroy(gMutexID)     Endif     gTH = 0     Stopit = 1 END FUNCTION ' ' PURPOSE: Get a simple status message regarding the thread FUNCTION Status CDECL () AS INTEGER export     Dim ret as integer     gCalls +=1     mutexlock(gMutexID)         ret = gState     mutexunlock(gMutexID)     'print "Status gState:="; gState     Status = ret END FUNCTION function Calls CDECL () as integer export     Calls = gCalls end function


The interface file thdll.bi
'FILENAME: th.bi 'PURPOSE:  Declarations for exported functions in thdll.bas ' 'NOTE: I got weired results before I did it all from scratch and aded on function, on declaration '     testcode in the runer and compiled. Did that until all functions were added. '     So I suspect that you can get in trouble if the function sequence in this file does not follow '     the sequence in the dll file. BUT I'M NOT SERTAN! declare function AddNumbers CDECL lib "thdll" alias "AddNumbers" ( byval operand1 as integer, byval operand2 as integer ) as integer declare FUNCTION Startit CDECL lib "thdll" alias "Startit" () AS INTEGER declare FUNCTION Stopit CDECL lib "thdll" alias "Stopit" () AS INTEGER declare FUNCTION Status CDECL lib "thdll" alias "Status" () AS INTEGER declare FUNCTION Calls CDECL lib "thdll" alias "Calls" () AS INTEGER


The freebasic test application (console): thrun.bas
'FILENAME: thrun.bas 'COMPILE: fbc thrun.bas 'PURPOSE: test functionality in thdll.bas 'USAGE:   Run in command box. thdll.dll must be in path (same folder) #include "thdll.bi"          ' Include file containing dll api interface randomize timer  x = rnd * 10  y = rnd * 10 print x; " +"; y; " ="; AddNumbers( x, y ) dim nTh as integer nTh = Startit()    'Starting the thread while n <= 10        'Let it work for a while     print "Status:="; Status()     sleep(333) Wend nTh = Stopit()      'Stop the thread print "Finished : "; Status(); Calls()


The AutoIt test application: thrun.au3
Plain Text         
;FILENAME: thrun.au3 ; ;mutithreaddll runner local $dllfilename = @ScriptDir & "\" & "thdll.dll" local $dll = DllOpen($dllfilename) local $ret if $dll = - 1 then    msgbox(16, "ERROR", "Could not load dll " & $dllfilename) Else    MsgBox(0,"ADDNUMBERS","Just a dll call test" & @CRLF & "2 + 2 = " & apiAddNubers(2, 2))    apiStartit()    while (apiStatus() < 20)       ConsoleWrite(apiStatus() & " - ")       sleep(900)    Wend    MsgBox(0,"FINISHED","Loop finished: status():=" & apiStatus()) EndIf exit Func OnAutoitExit()    msgbox(0,"TERMINATING", "OnAutoitExit")    apiStopit()    if $dll <> -1 then       DllClose($dll)    endif EndFunc Func apiStartit()    Local $ret = dllcall($dll, "int","Startit")    Local $err = @error    if $err <> 0 then       DllError($err)    EndIf      Return $ret[0] EndFunc Func apiStopit()    Local $ret = dllcall($dll, "int", "Stopit")    Local $err = @error    if $err <> 0 then       DllError($err)    EndIf      Return $ret[0] EndFunc Func apiStatus()    Local $ret = dllcall($dll, "int", "Status")    Local $err = @error    if $err <> 0 then       DllError($err)    EndIf      Return $ret[0] EndFunc Func apiAddNubers($arg1, $arg2)        Local $ret = dllcall($dll , "int", "AddNumbers", "int", $arg1, "int", $arg2)    Local $err = @error    if $err <> 0 then       DllError($err)       $ret = -1    EndIf    Return $ret[0] EndFunc Func DllError($err)    Local $errMessage    switch $err       case 1          $errMessage = "Unable to use the DLL file"       case 2          $errMessage = "unknown return type"       case  3          $errMessage = "function not found in the DLL file"       case Else          $errMessage = "Unknow error number: " & $err    EndSwitch    msgbox(16, "DllError", "Error occured" & @CRLF & $errMessage) EndFunc


Happy coding, Uten

Attached Files









#2 ptrex

ptrex

    Universalist

  • MVPs
  • 2,420 posts

Posted 02 May 2006 - 09:01 AM

@Uten

This is very enlightning for those who want to create own written DLL's, and glue into AutoIT.

I am not a Freebasic man myself but it looks very inviting :think:

More examples are welcome if it expands to possibilities of AutoIT.

Very nice !!

#3 SmOke_N

SmOke_N

    It's not what you know ... It's what you can prove!

  • Moderators
  • 15,730 posts

Posted 02 May 2006 - 09:08 AM

@Uten

This is very enlightning for those who want to create own written DLL's, and glue into AutoIT.

I am not a Freebasic man myself but it looks very inviting :(

More examples are welcome if it expands to possibilities of AutoIT.

Very nice !!

Yeah, I poked around in the forum for the first time today (saw a couple of your post too uten :think: ), the syntax looks easy enough to get down (a tad confusing in parts), but the possibility of effortlessly multithreading this way is appealing indeed (finally have a need for it after all this time with 1 of my scripts).

I haven't downloaded it yet, I'm going to do some more reading first, but thank you so much for the continued enlightenment and possible solutions for non-existant options at this time!

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.


#4 Uten

Uten

    stupid is as stupid does..

  • Active Members
  • PipPipPipPipPipPip
  • 1,989 posts

Posted 02 May 2006 - 02:03 PM

I might add that this was my first attempt at doing anything with freebasic. :( I did some reading about it and in the help files a while ago and thought it would be worth a try. It took me more than the three hours I thought I would have to spend to get it going, but now it is done.

The compiler is quite young so I think one should expect hiccups along the way. But it is open source, (and if I recall correctly the current compiler is written in freebasic, so if it does not fit your bill you can do something about it :think:

#5 jackyyll

jackyyll

    Polymath

  • Active Members
  • PipPipPipPip
  • 214 posts

Posted 03 May 2006 - 01:29 AM

Good stuff! ^^ Gonna use this in my next project .. if i ever start it lol

#6 themax90

themax90

    A new beginning

  • Active Members
  • PipPipPipPipPipPip
  • 1,265 posts

Posted 28 July 2006 - 06:35 PM

I seriously need AutoIt to support multithreading. Singlethread makes networking near impossible. I would love to hear a method that works.

#7 arcker

arcker

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 581 posts

Posted 30 July 2006 - 10:24 AM

1

-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

 

Projects :

  • Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here

#8 Uten

Uten

    stupid is as stupid does..

  • Active Members
  • PipPipPipPipPipPip
  • 1,989 posts

Posted 30 July 2006 - 11:42 AM

+1

???

@AutoIt Smith: A search and read session in the forums will explain why AutoIt is not multithreading ready by itselfe (and I'm shure you allready know this.. :whistle: ). It was not designed for multithreading and the code is not reentrant safe.

If we, the userbase, really want it to be multithreaded I think we have to take the provided source and make it thread safe (as a profe of consept) and then hope the developers of AutoIt will accept the changes and let the people whome has doen them make the requiered changes to the rest of the AutoIt code or do it them selfe. If you want to do this remember that size matters both to the community and the developers.

It should not be to much hazzle to make a mulithreaded networking component (dll or plugin) in freebasic (or C++) and use it in AutoIt.

#9 The Kandie Man

The Kandie Man

    All Your Base Are Belong To Us

  • Active Members
  • PipPipPipPipPipPip
  • 950 posts

Posted 20 November 2006 - 05:54 AM

Yes, this should come in quite handy. As you guys probably know i have written a search engine in autoit and right now i am using a FreeBasic dll to do the searching since it is faster than autoit. The only problem is that i need to create another thread so that the search function in the dll doesn't pause the whole program as it searches for files which only take a couple seconds, but the program should never be unresponsive.

Thanks Uten. I will probably end up writing this into my searchengine.dll. :lmao:

-The Kandie Man


EDIT:
Got it to work. Woot! Now all i have to do is some slight modification to my main autoit search engine script. ;)

Edited by The Kandie Man, 20 November 2006 - 07:02 AM.

"So man has sown the wind and reaped the world. Perhaps in the next few hours there will no remembrance of the past and no hope for the future that might have been." & _"All the works of man will be consumed in the great fire after which he was created." & _"And if there is a future for man, insensitive as he is, proud and defiant in his pursuit of power, let him resolve to live it lovingly, for he knows well how to do so." & _"Then he may say once more, 'Truly the light is sweet, and what a pleasant thing it is for the eyes to see the sun.'" - The Day the Earth Caught Fire

#10 wraithdu

wraithdu

    this noise inside my head

  • MVPs
  • 2,413 posts

Posted 12 July 2008 - 03:53 PM

I was very impressed by this and wanted to learn FreeBASIC to try and create some shell extensions for AutoIt (not there yet though). So to start learning I expanded on this example a bit to something a bit more AutoIt relevant, and that is threaded Message Boxes. Simple, but a good place to start and illustrate the example.

The example script I have demonstrates a few things that can be done. First is the use of mutexes in FreeBASIC to control threads. I've commented out 2 of the Mutex*** lines so all the message boxes pop up at once to demonstrate the threading, but if you put them back in and recompile the DLL then the boxes will come up one at a time, but the threads will be queued, meaning your script is still running and the closing / opening of the boxes is independent.

Second is an example of passing an array of information back to AutoIt. The _GetMutex() function passes back a pointer to a 2 element array with the handles of the 2 created mutexes. The values are retrieved by creating a DllStruct at the pointer.

Third is an example of properly waiting for all the threads to terminate before closing the AutoIt script. The main message boxes use the _ThreadWait() function in a loop, and the _GetMutex() boxes are stored by the DLL, and use the _WaitFinished() function to wait for them to close. I tried to put this loop in the Destructor so the DLL would wait automatically, but it didn't work. For some reason the DLL cannot see that the threads are closed and so it hangs in the loop. If anyone knows why, please do tell.

Oh, it's also got an elementary use of Types. This is the first time I've used one, so it was a good learning experience. I tried to pass a type structure back to AutoIt in the _GetMutex() function, and while AutoIt got the pointer correctly, I could not retrieve the data with the DllStruct like I could with the array. If anyone knows the answer to that one, I'd like to know as well.

This could pretty easily be extended for any functions you need to run threaded from an AutoIt script. I hope it's useful!

thdll.dll source (thdll.bas)
Plain Text         
#Include Once "windows.bi" Dim Shared As Any Ptr hMutex, tMutex, mutexptr(1) ReDim Shared As Any Ptr mboxwait(0) Type boxinfo     hWnd As HWND     As String lpText, lpCaption     uType As UInteger End Type Dim Shared mbox As boxinfo Sub _onstart Constructor     hMutex = MutexCreate()     tMutex = MutexCreate()     mutexptr(0) = hMutex     mutexptr(1) = tMutex End Sub Sub _tMessageBox (mPtr As boxinfo Ptr)     Dim info As boxinfo = *mPtr     MutexUnlock(tMutex)     '   MutexLock(hMutex)         MessageBox(info.hWnd, info.lpText, info.lpCaption, info.uType) '   MutexUnLock(hMutex) End Sub Function _MessageBox Cdecl Alias "_MessageBox" (ByVal hWnd As HWND, ByVal lpText As String, ByVal lpCaption As String, ByVal uType As UInteger) As Any Ptr Export     Dim hThread As Any Ptr         MutexLock(tMutex)     mbox.hWnd = hWnd     mbox.lpText = lpText     mbox.lpCaption = lpCaption     mbox.uType = uType     hThread = ThreadCreate(Cast(Any Ptr, @_tMessageBox), @mbox)     Return hThread End Function Function _GetMutex Cdecl Alias "_GetMutex" () As Any Ptr Export     Dim hThread As Any Ptr         hThread = _MessageBox(NULL, "Mutex ptr:  0x" & Hex(@mutexptr(0)) & Chr(13) & "hMutex:  0x" & Hex(hMutex) & Chr(13) & "tMutex:  0x" & Hex(tMutex), "INFO", MB_OK Or MB_ICONEXCLAMATION)     If mboxwait(UBound(mboxwait)) <> 0 Then         ReDim Preserve mboxwait(UBound(mboxwait) + 1)         mboxwait(UBound(mboxwait)) = hThread     Else         mboxwait(UBound(mboxwait)) = hThread     EndIf     Return @mutexptr(0) End Function Function _WaitThread Cdecl Alias "_WaitThread" (ByVal wThread As Any Ptr) As Integer Export     ThreadWait(wThread)     Return ERROR_SUCCESS End Function Function _WaitFinished Cdecl Alias "_WaitFinished" () As Integer Export     Dim i As Integer         For i = 0 To UBound(mboxwait)         ThreadWait(mboxwait(i))     Next i     Return ERROR_SUCCESS End Function Sub _OnExit Destructor     MutexDestroy(hMutex)     MutexDestroy(tMutex) End Sub


And the example AutoIt script. Watch the console for the output information.
NOTE: The DLL must use DllOpen() / DllClose() so the mutex and other information persists across DLL calls.
Plain Text         
$dllname = @ScriptDir & "\thdll.dll" $dll = DllOpen($dllname) For $i = 1 To 3     $ret = DllCall($dll, "ptr:cdecl", "_GetMutex") Next ConsoleWrite("Mutex array ptr: " & $ret[0] & @CRLF) $mutex = DllStructCreate("ptr m1; ptr m2", $ret[0]) ConsoleWrite("Mutex 1: " & DllStructGetData($mutex, "m1") & @CRLF) ConsoleWrite("Mutex 2: " & DllStructGetData($mutex, "m2") & @CRLF & @CRLF) Dim $thread[3] For $i = 1 To 3     $ret = DllCall($dll, "ptr:cdecl", "_MessageBox", _                             "hwnd", Chr(0), _                             "str", "Message Box " & $i, _                             "str", "Thread Test", _                             "uint", BitOR(0, 64) _                             )     ConsoleWrite("Error: " & @error & @CRLF)     ConsoleWrite("Ret: " & $ret[0] & @CRLF)     $thread[$i - 1] = $ret[0] Next ConsoleWrite(@CRLF & "-> ** do stuff while message boxes are up **" & @CRLF & @CRLF) For $i = 0 To 2     $ret = DllCall($dll, "int:cdecl", "_WaitThread", "ptr", $thread[$i])     ConsoleWrite("Thread " & $thread[$i] & " done." & @CRLF)     ConsoleWrite("Error: " & @error & @CRLF)     ConsoleWrite("Ret: " & $ret[0] & @CRLF) Next ConsoleWrite(@CRLF & "-> ** Waiting for _GetMutex() message boxes to close... **" & @CRLF) DllCall($dll, "int:cdecl", "_WaitFinished") ConsoleWrite(@CRLF & "-> ** All threads finished! **" & @CRLF) DllClose($dll) ConsoleWrite("DLL closed." & @CRLF)

Edited by wraithdu, 12 July 2008 - 03:55 PM.


#11 Beege

Beege

    Universalist

  • MVPs
  • 895 posts

Posted 11 February 2009 - 09:35 AM

I know this is an old topic but autoit is crashing with this dll now. And any dll i try to make with freebasic for that matter. Any Ideas?

>AutoIT3.exe ended.rc:-1073741819
>Exit code: -1073741819 Time: 5.522

#12 ProgAndy

ProgAndy

    You need AutoItObject

  • MVPs
  • 2,508 posts

Posted 11 February 2009 - 02:14 PM

You can create threads with Autoit, so you don't need a DLl to do that.
You just mustn't use an AutoIt-Function with DLLCallbackRegister as the Thread-Functions. (The thread runs, but AutoIt crahses after a few secs)
So yo have to use just one func in the DLL which wil be the ThreadProc. For Messageboxes you could use the MessageBoxIndirect from user32.dll.
Example at the end of script:
AutoIt         
Global Const $STATUS_PENDING = 0x103 Global Const $STILL_ACTIVE = $STATUS_PENDING ; ThreadID is @extended ;=============================================================================== ; ; Function Name:   _Thread_Create ; Description::    Creates a thread ; Parameter(s):    see MSDN (lpThreadId is removed) ; Requirement(s):  minimum Win2000 ; Return Value(s): see MSDN ;                  @extended will be ThreadID ;                  On error, @error will be set to 1 ; Author(s):       Prog@ndy ; ;=============================================================================== ; Func _Thread_Create($lpThreadAttributes, $dwStackSize, $lpStartAddress, $lpParameter, $dwCreationFlags)     Local $result = DllCall("kernel32.dll","ptr","CreateThread", "ptr", $lpThreadAttributes, "dword", $dwStackSize, "ptr", $lpStartAddress, "ptr", $lpParameter, "dword", $dwCreationFlags, "dword*", 0)     Return SetError($result[0]=0,$result[6],$result[0]) EndFunc ;=============================================================================== ; ; Function Name:   _Thread_Terminate ; Description::    Terminates a thread ; Parameter(s):    see MSDN ; Requirement(s):  minimum Win2000 ; Return Value(s): see MSDN ;                  On error, @error will be set to 1 ; Author(s):       Prog@ndy ; ;=============================================================================== ; Func _Thread_Terminate($hThread,$dwExitCode)     Local $result = DllCall("Kernel32.dll","int","TerminateThread","ptr",$hThread,"dword",$dwExitCode)     Return SetError($result[0]=0,0,$result[0]) EndFunc ;=============================================================================== ; ; Function Name:   _Thread_Exits ; Description::    Exits the current thread ; Parameter(s):    see MSDN ; Requirement(s):  minimum Win2000 ; Return Value(s): none ; Author(s):       Prog@ndy ; ;=============================================================================== ; Func _Thread_Exit($dwExitCode)     DllCall("Kernel32.dll","none","ExitThread","dword",$dwExitCode) EndFunc ;=============================================================================== ; ; Function Name:   _Thread_GetExitCode ; Description::    retrieves ExitCode of a thread ; Parameter(s):    see MSDN ; Requirement(s):  minimum Win2000 ; Return Value(s): see MSDN ;                  On error, @error will be set to 1 ; Author(s):       Prog@ndy ; ;=============================================================================== ; Func _Thread_GetExitCode($hThread)     Local $result = DllCall("Kernel32.dll","int","GetExitCodeThread","ptr",$hThread,"dword*",0)     Return SetError($result[0]=0,0,$result[2]) EndFunc ;=============================================================================== ; ; Function Name:   _Thread_GetID ; Description::    retrieves ThreadID of a thread ; Parameter(s):    see MSDN ; Requirement(s):  minimum Win2000 ; Return Value(s): see MSDN ;                  On error, @error will be set to 1 ; Author(s):       Prog@ndy ; ;=============================================================================== ; Func _Thread_GetID($hThread)     Local $result = DllCall("Kernel32.dll","dword","GetThreadId","ptr",$hThread)     Return SetError($result[0]=0,0,$result[0]) EndFunc ;=============================================================================== ; ; Function Name:   _Thread_GetPriority ; Description::    retrieves priority of a thread ; Parameter(s):    see MSDN ; Requirement(s):  minimum Win2000 ; Return Value(s): see MSDN ;                  On error, @error will be set to 1 ; Author(s):       Prog@ndy ; ;=============================================================================== ; Func _Thread_GetPriority($hThread)     Local $result = DllCall("Kernel32.dll","int","GetThreadPriority","ptr",$hThread)     Return SetError($result[0]=0,0,$result[0]) EndFunc ;=============================================================================== ; ; Function Name:   _Thread_SetPriority ; Description::    sets priority of a thread ; Parameter(s):    see MSDN ; Requirement(s):  minimum Win2000 ; Return Value(s): see MSDN ;                  On error, @error will be set to 1 ; Author(s):       Prog@ndy ; ;=============================================================================== ; Func _Thread_SetPriority($hThread,$nPriority)     Local $result = DllCall("Kernel32.dll","int","SetThreadPriority","ptr",$hThread,"int",$nPriority)     Return SetError($result[0]=0,0,$result[0]) EndFunc ;=============================================================================== ; ; Function Name:   _Thread_Suspend ; Description::    suspends a thread ; Parameter(s):    see MSDN ; Requirement(s):  minimum Win2000 ; Return Value(s): see MSDN ;                  On error, @error will be set to 1 ; Author(s):       Prog@ndy ; ;=============================================================================== ; Func _Thread_Suspend($hThread)     Local $result = DllCall("Kernel32.dll","int","SuspendThread","ptr",$hThread)     Return SetError($result[0]=-1,0,$result[0]) EndFunc ;=============================================================================== ; ; Function Name:   _Thread_Resume ; Description::    resumes a thread ; Parameter(s):    see MSDN ; Requirement(s):  minimum Win2000 ; Return Value(s): see MSDN ;                  On error, @error will be set to 1 ; Author(s):       Prog@ndy ; ;=============================================================================== ; Func _Thread_Resume($hThread)     Local $result = DllCall("Kernel32.dll","int","ResumeThread","ptr",$hThread)     Return SetError($result[0]=-1,0,$result[0]) EndFunc ;=============================================================================== ; ; Function Name:   _Thread_Wait ; Description::    Waits for a thread to terminate ; Parameter(s):    $hThread  - Handle of thread ;                  $nTimeOut - [optional] Timeout (default: 0xFFFFFFFF => INFINTE) ; Requirement(s):  minimum Win2000 ; Return Value(s): Success: true ;                  on TimeOut, @eeor will be set to -1 ;                  On error, @error will be set to 1 ; Author(s):       Prog@ndy ; ;=============================================================================== ; Func _Thread_Wait($hThread,$nTimeout=0xFFFFFFFF)     Local $result = DllCall("Kernel32.dll", "dword", "WaitForSingleObject", "ptr", $hThread, "int", $nTimeout)     If @error Then Return SetError(2,0,0)     Switch $result[0]         Case -1, 0xFFFFFFFF             Return SetError(1,0,0)         Case 0x00000102             Return SetError(-1,0,1)         Case Else             Return 1     EndSwitch EndFunc #include <WinAPI.au3> $tagMSGBOXPARAMS = _         "UINT cbSize;" & _         "HWND hwndOwner;" & _         "ptr hInstance;" & _         "ptr lpszText;" & _         "ptr lpszCaption;" & _         "DWORD dwStyle;" & _         "ptr lpszIcon;" & _         "UINT_PTR dwContextHelpId;" & _         "ptr lpfnMsgBoxCallback;" & _         "DWORD dwLanguageId;" ; creates a struct for an Unicode-String Func _UnicodeStruct($text)     ; Prog@ndy     Local $s = DllStructCreate("wchar[" & StringLen($text)+1 & "]")     DllStructSetData($s,1,$text)     Return $s EndFunc ; retrieves Address of a function Func _Thread_GetProcAddress($hModule,$sProcname)     ; Prog@ndy     Local $result = DllCall("kernel32.dll","ptr","GetProcAddress","hwnd",$hModule,"str",$sProcname)     Return $result[0] EndFunc ; Struct to send to the Thread ; in this case the MsgBox-Params $MSGBOXPARAMS = DllStructCreate($tagMSGBOXPARAMS) DllStructSetData($MSGBOXPARAMS,"cbSize",DllStructGetSize($MSGBOXPARAMS)) $stText = _UnicodeStruct("The messageBox in a separate thead!") DllStructSetData($MSGBOXPARAMS,"lpszText",DllStructGetPtr($stText)) $stCaption = _UnicodeStruct("Caption") DllStructSetData($MSGBOXPARAMS,"lpszCaption",DllStructGetPtr($stCaption)) DllStructSetData($MSGBOXPARAMS,"dwStyle",17) ; msgBox-style ; Use MessageBoxIndirect Unicode as ThreadProc ; normal MessageBox doesn't work, since CreateThread just has one possible parameter. Local $hThreadProc = _Thread_GetProcAddress(_WinAPI_GetModuleHandle("user32.dll"),"MessageBoxIndirectW") $hThread = _Thread_Create(0 ,0, $hThreadProc, DllStructGetPtr($MSGBOXPARAMS), 0) $ThreadID = @extended While MsgBox(69, "main", "Main script is not blocked" )=4 WEnd MsgBox(0, "Thread-Info", "Handle: " & $hThread & @CRLF & "Thread-ID: " & $ThreadID) _Thread_Wait($hThread) $code = _Thread_GetExitCode($hThread) MsgBox(0, 'Thread ended', "Threaded MsgBox returned: " & $code)

Edited by ProgAndy, 21 May 2009 - 07:18 PM.

*GERMAN* Posted Image [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

#13 wraithdu

wraithdu

    this noise inside my head

  • MVPs
  • 2,413 posts

Posted 11 February 2009 - 05:35 PM

@ProgAndy
Nice little example. Is there any reason you don't use _WinAPI_WaitForSingleObject($hThread) in your _Thread_Wait() function?

#14 Beege

Beege

    Universalist

  • MVPs
  • 895 posts

Posted 11 February 2009 - 08:32 PM

yes that was a great example. Thanks! Im going to play with those. Anyway I figured out the problem regarding freebasic dll. Functions need to be called with cdecl after the return value for this dll.

Ex: $ret = dllcall($dll, "int:cdecl","Startit")

#15 ProgAndy

ProgAndy

    You need AutoItObject

  • MVPs
  • 2,508 posts

Posted 12 February 2009 - 03:08 PM

@ProgAndy
Nice little example. Is there any reason you don't use _WinAPI_WaitForSingleObject($hThread) in your _Thread_Wait() function?

There is just one reason: i forgot to use it ... Here it is:
AutoIt         
;=============================================================================== ; ; Function Name:   _Thread_Wait ; Description::    Waits for a thread to terminate ; Parameter(s):    $hThread  - Handle of thread ;                  $nTimeOut - [optional] Timeout (default: 0xFFFFFFFF => INFINTE) ; Requirement(s):  minimum Win2000 ; Return Value(s): Success: true ;                  on TimeOut, @eeor will be set to -1 ;                  On error, @error will be set to 1 ; Author(s):       Prog@ndy ; ;=============================================================================== ; Func _Thread_Wait($hThread,$nTimeout=0xFFFFFFFF)     Local $result = DllCall("Kernel32.dll", "dword", "WaitForSingleObject", "ptr", $hThread, "int", $nTimeout)     If @error Then Return SetError(2,0,0)     Switch $result[0]         Case -1, 0xFFFFFFFF             Return SetError(1,0,0)         Case 0x00000102             Return SetError(-1,0,1)         Case Else             Return 1     EndSwitch EndFunc

Edited by ProgAndy, 12 February 2009 - 03:08 PM.

*GERMAN* Posted Image [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

#16 rajeshwaran

rajeshwaran

    Seeker

  • Active Members
  • 40 posts

Posted 06 September 2010 - 07:11 AM

Hi ProgAndy,

The implementation is simple, still I cant understand the below line
_Thread_GetProcAddress(_WinAPI_GetModuleHandle("user32.dll"),"MessageBoxIndirectW")


Can you provide a simple example to just call a user defined function MyFunction() inside the _Thread_Create() function

$hThread = _Thread_Create(0 ,0, MyFunction, DllStructGetPtr($MSGBOXPARAMS), 0)


#17 ProgAndy

ProgAndy

    You need AutoItObject

  • MVPs
  • 2,508 posts

Posted 06 September 2010 - 09:29 AM

What do you mean with user defined function? A function written in AutoIt? That won't work since the AutoIt-interpreter is not threadsafe.

What you can do is creating a function in a DLL and use that as a thread:
DLLOpen("myThreadFunc.dll") ;<- open DLL $hDLLHandle = _WinAPI_GetModuleHandle("myThreadFunc.dll") ; get address of the loaded DLL $hThreadProc = _Thread_GetProcAddress($hDLLHandle, "MyThreadFunc") ; get address of the function in the dll

*GERMAN* Posted Image [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

#18 rajeshwaran

rajeshwaran

    Seeker

  • Active Members
  • 40 posts

Posted 06 September 2010 - 09:46 AM

Thank you very much for your fast response.

If I create a function in DLL then, I cant access AutoIt Script file resoruces (variables/functions).

So how to overcome this problem ?




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users