Jump to content

_WinAPI_WaitForMultipleObjects


Recommended Posts

_WinAPI_WaitForSingleObject (- Waits until the specified object is in the signaled state)
_WinAPI_WaitForMultipleObjects (- Waits until one or all of the specified objects are in the signaled state)

How to rewrite this code using  _WinAPI_WaitForMultipleObjects

 

& how to do.....
if {ESC} IsPressed then Exit process will be on hold
until __ReadData or __WriteData which ever process is running is complete / timeout.

;~ How to rewrite this code using _WinAPI_WaitForMultipleObjects
#include <Date.au3>
HotKeySet("{ESC}", "_Exit")

Example()
Func Example()
    Local $Loop_toRun = 10
    Local $GetData
    Local $i = 0
    Do
        sleep(250)
        ConsoleWrite("> " & $i & ") Data download started time " & _NowTime() & @CRLF)
        $GetData = __ReadData()
        ConsoleWrite("> " & $i & ") Data download done " & _NowTime() & @CRLF)
        __WriteData($GetData, $i)
        $i = $i + 1
    Until $i = $Loop_toRun
EndFunc

Func __ReadData()
    Local $dData = InetRead("https://www.autoitscript.com/forum/")
    Local $sData = BinaryToString($dData)
    sleep(2000)     ;~ intentional sleep to delay the process
    Return $sData
EndFunc

Func __WriteData($GtData, $i)
    ConsoleWrite("+ " & $i & ") writing Data.... " & _NowTime() & @CRLF)
    Local $WData = $GtData & @CRLF
    Local $sFilePath = @ScriptDir & '\test' & $i & '.txt'
    Local $hFileOpen = FileOpen($sFilePath, 1)
    sleep(5000)     ;~ intentional sleep to delay the process
    FileWrite($hFileOpen, $WData)
    FileClose($hFileOpen)
    ConsoleWrite("+ " & $i & ") writing complete " & _NowTime() & @CRLF)
EndFunc

Func _Exit()
    Exit
EndFunc ;==>

 

Edited by jugador
Link to comment
Share on other sites

So, I’m not sure why you want to use _WinWaitMultipleObjects here, is there some other process contended for a shared resource?

Anyway, I think what you want can be achieved fairly easily with these mods(not tested).

I’ve made it wait until the write is done, no matter whether it’s interrupted in the read or write.  Only because it didn’t make sense to wait for the read to finish only to kill it without saving.  But if that’s what you want you can put a check at the end of read, like the one after write.

;~ How to rewrite this code using _WinAPI_WaitForMultipleObjects
#include <Date.au3>
HotKeySet("{ESC}", "_Exit")

Global $bFinished=True, $bMustExit=False

Example()
Func Example()
    Local $Loop_toRun = 10
    Local $GetData
    Local $i = 0
    Do
        sleep(250)
        ConsoleWrite("> " & $i & ") Data download started time " & _NowTime() & @CRLF)
        $GetData = __ReadData() 
        ConsoleWrite("> " & $i & ") Data download done " & _NowTime() & @CRLF)
        __WriteData($GetData, $i)
        $i = $i + 1
    Until $i = $Loop_toRun
EndFunc

Func __ReadData()
    $bFinished=False
    Local $dData = InetRead("https://www.autoitscript.com/forum/")
    Local $sData = BinaryToString($dData)
    sleep(2000)     ;~ intentional sleep to delay the process
   
    Return $sData
EndFunc

Func __WriteData($GtData, $i)
    ConsoleWrite("+ " & $i & ") writing Data.... " & _NowTime() & @CRLF)
    Local $WData = $GtData & @CRLF
    Local $sFilePath = @ScriptDir & '\test' & $i & '.txt'
    Local $hFileOpen = FileOpen($sFilePath, 1)
    sleep(5000)     ;~ intentional sleep to delay the process
    FileWrite($hFileOpen, $WData)
    FileClose($hFileOpen)
    ConsoleWrite("+ " & $i & ") writing complete " & _NowTime() & @CRLF)
    $bFinished=True
    If $bMustExit Then _Exit()
EndFunc

Func _Exit()
   If $bFinished Then Exit
   $bMustExit=True
EndFunc ;==>

 

Code hard, but don’t hard code...

Link to comment
Share on other sites

@jugador  See my Named Pipe IPC UDF in my signature for a complete example of the usage of _WinAPI_WaitForMultipleObjects with _WinAPI_CreateEvent.  The basis is to use overlapped option of WinAPI (or other similar functions). Let me know if you have further questions.

Edited by Nine
Link to comment
Share on other sites

12 hours ago, jugador said:

it's just an example

I think you may want to use a better example - Autoit is not multi-threaded - therefore you need to test with a multi-process example.
 @Nine’s Named Pipe is an example of IPC - InterProcessCommunication.

Not to say that a single working program can’t somehow use WaitForMultipleObjects, if one is determined, it’s just that there is usually an easier way.

Code hard, but don’t hard code...

Link to comment
Share on other sites

@JockoDundee Just to start with basic I put this example. Instead of two different function think as two different programs

@Nine Need more time to understand your code properly

Anyways Guys if any error in coding please do mention.

#include <Date.au3>
#include <WinAPIHObj.au3>
#include <WinAPIProc.au3>

HotKeySet("{ESC}", "_Exit")

Global $Esc_isTrue = False
Global $g_tEvents = DllStructCreate("handle Event[2];")
$g_tEvents.Event(1) = _WinAPI_CreateEvent(0, True, False)
$g_tEvents.Event(2) = _WinAPI_CreateEvent(0, True, False)

Example()

Func Example()
    Local $Loop_toRun = 5
    Local $GetData
    Local $iEvent
    Local $i = 0
    Do
        sleep(250)
        If _WinAPI_WaitForSingleObject($g_tEvents.Event(2), 0) <> 0 Then
            $GetData = __ReadData()
        Else
            ConsoleWrite("2nd Process closing error" & @CRLF)
            Exit
        Endif

        $iEvent = _WinAPI_WaitForMultipleObjects(2, $g_tEvents, False, 100)
        Switch $iEvent
            Case 0
                _WinAPI_ResetEvent($g_tEvents.Event(1))
                If $Esc_isTrue = True Then _Exit()
                __WriteData($GetData, $i)
            Case -1 ;Error
                Exit
        EndSwitch
        If $Esc_isTrue = True Then _Exit()
        $i = $i + 1
    Until $i = $Loop_toRun

$Esc_isTrue = True
_Exit()
EndFunc   ;==>Example

Func __ReadData()
    _WinAPI_SetEvent($g_tEvents.Event(1))
    ConsoleWrite("> ) Data download started time " & _NowTime() & @CRLF)
    Local $dData = InetRead("https://www.autoitscript.com/forum/")
    Local $sData = BinaryToString($dData)
    sleep(3000)
    ConsoleWrite("> ) Data download end time " & _NowTime() & @CRLF)
    Return $sData
EndFunc   ;==>Example

Func __WriteData($GtData, $i)
    _WinAPI_SetEvent($g_tEvents.Event(2))
    ConsoleWrite("+ " & $i & ") writing Data.... " & _NowTime() & @CRLF)
    Local $WData = $GtData & @CRLF
    Local $sFilePath = @ScriptDir & '\test' & $i & '.txt'
    Local $hFileOpen = FileOpen($sFilePath, 1)
    FileWrite($hFileOpen, $WData)
    FileClose($hFileOpen)
    sleep(3000)
    ConsoleWrite("+ " & $i & ") writing complete " & _NowTime() & @CRLF)
    _WinAPI_ResetEvent($g_tEvents.Event(2))
EndFunc   ;==>Example

Func _Exit()
    If $Esc_isTrue = False Then
        $Esc_isTrue = True
        Return
    Endif
    _WinAPI_CloseHandle($g_tEvents.Event(1))
    _WinAPI_CloseHandle($g_tEvents.Event(2))
    Exit
EndFunc ;==>

 

Edited by jugador
Link to comment
Share on other sites

As far as I can see (I did not test your script), there is no obvious flaw in your code.  However, I do not see the advantage of using events (but there is not harm doing so).  Normal usage of events is to launch an overlapped function, and while that function is working you are free to do something else.  When the overlapped function is completed, it is signaled as an event and you can react to it.

Currently your code set manually events, because you are not using overlapped functions.  You could do the same with global variables.  But like I said, there is no harm doing it that way.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...