Thanks mk-soft. When I run your solution, I am sometimes getting a crash on the very last line (the Delay() statement)
The crash seems to be random, but if I run the code 10-20 times I always see it eventually
Not for me, but the programme must always run until the last thread is finished. Even if Purebasic automatically kills the threads that are still running, this can lead to a crash.
Also, it is always best to work with the ThreadSafe option.
Another small change. Always declare the variables in procedures.
And important! Use EnableExplicit.
CompilerIf Not #PB_Compiler_Thread
CompilerError "Use Compiler Option ThreadSafe!"
CompilerEndIf
EnableExplicit
Structure ThreadData
ThreadID.i
Halt.i
Work.i
Counter.i
List IP.s()
EndStructure
Global Thread.ThreadData
Global Signal_Thread = CreateSemaphore(0) ; We are at state 0 (no jobs)
Global Mutex_Thread = CreateMutex() ; to protect the list
; The Thread
Procedure.i DoIt(dummy)
Protected IP.s = ""
; Set the state of working for the first time
Thread\Work = #False ; Thread is not working
Thread\Halt = #False ; Thread is not aborted by user
Repeat
; Wait for a signal
WaitSemaphore(Signal_Thread)
; Set working flag
Thread\Work = #True
; Check if user want to abort
If Thread\Halt = #True
Debug "Abort It"
Break ; jump after the ForEver statement (Closes Thread)
EndIf
; Be sure that no datas are in the var
IP = ""
; Lock the List in case of adding new "jobs"
LockMutex(Mutex_Thread)
; Get the first element of the "joblist"
If FirstElement(Thread\IP())
IP = Thread\IP()
DeleteElement(Thread\IP()) ; and delete it
EndIf
; Unlock it
UnlockMutex(Mutex_Thread)
; Show the result
If IP <> ""
Debug "IP - Lookup : " + IP
EndIf
Thread\Counter + 1
; Wait a little (if you dont want to flood a server with requests to get banned, maybe...)
; In this case of demo, it is to see some working
Delay(500)
; Set the working state to false again
Thread\Work = #False
ForEver
; Here the thread will end so you can restart it if you want
Thread\Halt = #False
Thread\Work = #False
Thread\ThreadID = #False
EndProcedure
; The Add Job Thing
Procedure.i AddIt(IP.s)
; Protect the List
LockMutex(Mutex_Thread)
; Add your job
AddElement(Thread\IP())
Thread\IP() = IP
Debug "Insert -> " + IP
; and unprotect it
UnlockMutex(Mutex_Thread)
; Now send a signal to the thread
SignalSemaphore(Signal_Thread)
EndProcedure
; The Stop Thread Thing
Procedure.i AbortIt()
; Set the Halt
Thread\Halt = #True
; If the thread is staying at "WaitSemaphore()" send a signal to start a loop
If Thread\Work = #False
SignalSemaphore(Signal_Thread)
EndIf
EndProcedure
; Demo
Thread\ThreadID = CreateThread(@DoIt(), 0)
Define i, StopAfter
; StopAfter = ElapsedMilliseconds() + (30 * 600) ; We gave him 600ms time to do the programs job
StopAfter = ElapsedMilliseconds() + Random(30 * 200, 30 * 100) ; a shorter Random Time (we need 30x100 for the FOR:NEXT loop as a minimum)
; Add the jobs
For i = 1 To 30
AddIt(Str(Random(255,0)) + "." + Str(Random(255,0)) + "." + Str(Random(255,0)) + "." + Str(Random(255,0)))
Delay(100)
Next
; Now wait for the random time
While ElapsedMilliseconds() <= StopAfter
Delay(1)
Wend
; No more time or program end
AbortIt()
; Wait for program
Delay(5000)
; And again Abort the thread, if the thread is working longer as expected
AbortIt()
Debug "We Inserted 30 Jobs and the thread do " + Str(Thread\Counter) + " of them"
Debug "Program ends"
End
Ok it is more to write (lazy programmers ) but this will be more comfortable....
PureBasic 6.10 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom
English is not my native language... (I often use DeepL to translate my texts.)
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too!Please visit my YouTube Channel