Thread state

Just starting out? Need help? Post your questions and find answers here.
Blankname
Enthusiast
Enthusiast
Posts: 120
Joined: Sun Oct 14, 2012 9:11 am

Thread state

Post by Blankname »

I'm trying to check if a thread is suspended or not, and can't seem to get the code I wrote to work.

Code: Select all

Procedure MainThread(parameter)
  Repeat
    Delay(1000)
    PrintN("Thread Message")
  ForEver
EndProcedure

OpenConsole()
Thread = CreateThread(@MainThread(), 1)
Timer = ElapsedMilliseconds()

Repeat
  Delay(1000)
  If WaitForSingleObject_(ThreadID(Thread), 0) = #WAIT_ABANDONED
    PrintN("Thread Suspended")
  EndIf
  Timed = ElapsedMilliseconds()-Timer
  If Timed > 5000
    PauseThread(Thread)
  EndIf
ForEver
User avatar
Demivec
Addict
Addict
Posts: 4257
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Thread state

Post by Demivec »

Blankname wrote:I'm trying to check if a thread is suspended or not, and can't seem to get the code I wrote to work.
#WAIT_ABANDONED is for a mutex object.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4944
Joined: Sun Apr 12, 2009 6:27 am

Re: Thread state

Post by RASHAD »

Not very accurate because you are using many delays
And you are not suppose to use consecutive PauseThread()

Code: Select all

Procedure MainThread(parameter)
  Repeat
    Delay(1000)
    PrintN("Thread Message")
  ForEver
EndProcedure

OpenConsole()
Thread = CreateThread(@MainThread(), 1)
Timer = ElapsedMilliseconds()

Repeat
  Delay(1000)
  If WaitForSingleObject_(ThreadID(Thread), 10000) = #WAIT_TIMEOUT	
    PrintN("Thread Suspended")
  EndIf
  Timed = ElapsedMilliseconds()-Timer
  If Timed > 5000 And pause = 0
    PauseThread(Thread)
    pause = 1
  EndIf
ForEver

Egypt my love
Blankname
Enthusiast
Enthusiast
Posts: 120
Joined: Sun Oct 14, 2012 9:11 am

Re: Thread state

Post by Blankname »

RASHAD wrote:Not very accurate because you are using many delays
And you are not suppose to use consecutive PauseThread()

Code: Select all

Procedure MainThread(parameter)
  Repeat
    Delay(1000)
    PrintN("Thread Message")
  ForEver
EndProcedure

OpenConsole()
Thread = CreateThread(@MainThread(), 1)
Timer = ElapsedMilliseconds()

Repeat
  Delay(1000)
  If WaitForSingleObject_(ThreadID(Thread), 10000) = #WAIT_TIMEOUT	
    PrintN("Thread Suspended")
  EndIf
;  Timed = ElapsedMilliseconds()-Timer
;  If Timed > 5000 And pause = 0
;    PauseThread(Thread)
;    pause = 1
  EndIf
ForEver

It ends up spurting "Thread Suspended" every 10 seconds when the timeout expires if you comment out the pausing. GetLastError_() returns 6 "Invalid Handle".
User avatar
Demivec
Addict
Addict
Posts: 4257
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Thread state

Post by Demivec »

Wouldn't it be easier to just record whether the thread is paused in a variable (or array, list, etc.) and then check that for its status?
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4944
Joined: Sun Apr 12, 2009 6:27 am

Re: Thread state

Post by RASHAD »

As Demivec stated you can use some other way to get it like Flag
Unfortunately WaitForSingleObject_() respond only for #WAIT_TIMEOUT event
That is how Fred designed CreateThread()
I guess you want a message when the Thread is paused or resumed instantly
Egypt my love
Blankname
Enthusiast
Enthusiast
Posts: 120
Joined: Sun Oct 14, 2012 9:11 am

Re: Thread state

Post by Blankname »

RASHAD wrote:As Demivec stated you can use some other way to get it like Flag
Unfortunately WaitForSingleObject_() respond only for #WAIT_TIMEOUT event
That is how Fred designed CreateThread()
I guess you want a message when the Thread is paused or resumed instantly
I'm spawning a couple of "checker threads" that's sole purpose is to make sure the main thread hasn't ended or been suspended.
User avatar
RichAlgeni
Addict
Addict
Posts: 935
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: Thread state

Post by RichAlgeni »

I use event handles to accomplish what you want. First create the events, I store them in dimensioned arrays:

Code: Select all

For threadNumber=0 To numberThreads
    thisEvent(threadNumber) = CreateEvent_(0, 0, 0, #ProgramName + "_Event_" + Str(threadNumber))
Next
Then I create threads for each event:

Code: Select all

For threadNumber=0 To numberThreads
    CreateThread(@ProcessRQST(), threadNumber)
Next
Here are the procedures, waiting forever:

Code: Select all

Procedure.i ProcessRQST(requestNumber.i)
    Repeat
        WaitForSingleObject_(thisEvent(requestNumber), #INFINITE)
        ...
The I can call the Windows API function to trigger the event:

Code: Select all

SetEvent_(thisEvent(threadToUse))
To end the process, I just set a global variable ShutDownNow to #True, then fire all of the events. If ShutDownNow is #True, the threaded procedures end.
jassing
Addict
Addict
Posts: 1885
Joined: Wed Feb 17, 2010 12:00 am

Re: Thread state

Post by jassing »

Blankname wrote:I'm spawning a couple of "checker threads" that's sole purpose is to make sure the main thread hasn't ended or been suspended.
Is "the main thread" the executable program being run, and it creates the "checker threads"?
If so, if the exe (and thus, 'the main thread') ends/exits/errors out/crashes, the "checker threads" will die with it.
Blankname
Enthusiast
Enthusiast
Posts: 120
Joined: Sun Oct 14, 2012 9:11 am

Re: Thread state

Post by Blankname »

jassing wrote:
Blankname wrote:I'm spawning a couple of "checker threads" that's sole purpose is to make sure the main thread hasn't ended or been suspended.
Is "the main thread" the executable program being run, and it creates the "checker threads"?
If so, if the exe (and thus, 'the main thread') ends/exits/errors out/crashes, the "checker threads" will die with it.
I'm spawning three new threads on AttachProcess(), one is the main executed code and the other two are the checker threads to make sure the first thread is running.
Blankname
Enthusiast
Enthusiast
Posts: 120
Joined: Sun Oct 14, 2012 9:11 am

Re: Thread state

Post by Blankname »

RichAlgeni wrote:I use event handles to accomplish what you want. First create the events, I store them in dimensioned arrays:

Code: Select all

For threadNumber=0 To numberThreads
    thisEvent(threadNumber) = CreateEvent_(0, 0, 0, #ProgramName + "_Event_" + Str(threadNumber))
Next
Then I create threads for each event:

Code: Select all

For threadNumber=0 To numberThreads
    CreateThread(@ProcessRQST(), threadNumber)
Next
Here are the procedures, waiting forever:

Code: Select all

Procedure.i ProcessRQST(requestNumber.i)
    Repeat
        WaitForSingleObject_(thisEvent(requestNumber), #INFINITE)
        ...
The I can call the Windows API function to trigger the event:

Code: Select all

SetEvent_(thisEvent(threadToUse))
To end the process, I just set a global variable ShutDownNow to #True, then fire all of the events. If ShutDownNow is #True, the threaded procedures end.
WaitForSingleObject waits until a thread is finished tho doesn't it? To clarify what I am doing I will post a example code below. The purpose is for a simple anti-cheat engine for my game, and the purpose for the checker threads it keep players from just simply suspending the main thread (with all the important checks) and bypassing it completely. With a few checker threads constantly monitoring the main thread, it will make it much harder to bypass with software like Process Explorer. Tho it would be better if every thread checked each other.

Code: Select all

Procedure MainThread(Value.i)
  Repeat
    ; All The Main Code
  ForEver
EndProcedure

Procedure CheckerThread(Value.i)
  Repeat
    ; Checks If Main Thread Is Still Active + Running (Not Suspended)
    ; Checks If Checker Thread 1 + 2 Is Still Active + Running (Not Suspended)
  ForEver
EndProcedure

ProcedureDLL AttachProcess(Instance)
  Thread1 = CreateThread(@MainThread(), 1)
  Thread2 = CreateThread(@CheckerThread(), 2)
  Thread3 = CreateThread(@CheckerThread(), 3)
EndProcedure
User avatar
RichAlgeni
Addict
Addict
Posts: 935
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: Thread state

Post by RichAlgeni »

WaitForSingleObject_(thisEvent(requestNumber), #INFINITE) can be used anywhere, not just in a thread. It waits the amount of time specified in the second parameter. In the above case, it will wait forever, but just until SetEvent_(thisEvent(requestNumber)) is executed, in which case it will go on it's way. You can also use a timer in the second parameter:

http://msdn.microsoft.com/en-us/library ... s.85).aspx

Once the timer expires, execution will continue in the same way as if an event fired. You don't need to use SetEvent, unless you want the execution to continue for any reason before a time expires.

You can use this in your checker threads to periodically wake up and check the main thread.
Blankname
Enthusiast
Enthusiast
Posts: 120
Joined: Sun Oct 14, 2012 9:11 am

Re: Thread state

Post by Blankname »

This works for me, ResumeThread doesn't return true until the specified thread is paused (suspended). So I don't have to suspend the thread at all, this is a much more efficient way to check if a thread is suspended (plus it just resumes it if it was).

Code: Select all

Global Thread1, Thread2

Procedure MainThread(Value.i)
  Repeat
    PrintN("Thread Message [" + Str(Random(99, 10)) + "]")
    Delay(1000)
  ForEver
EndProcedure

Procedure CheckerThread(Value.i)
  Repeat
    If IsThread(Thread1)
      If ResumeThread(Thread1)
        PrintN("Thread Suspended!")
      EndIf
    Else
      PrintN("Thread Killed!")
    EndIf
    Delay(1000)
  ForEver
EndProcedure

OpenConsole()

Thread1 = CreateThread(@MainThread(), 1)
Thread2 = CreateThread(@CheckerThread(), 2)

Repeat
  Delay(1)
ForEver
User avatar
RichAlgeni
Addict
Addict
Posts: 935
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: Thread state

Post by RichAlgeni »

Very good!
Post Reply