Threading questions

Ask for Help on Using the Language With Memory Hacking Software

Moderators: g3nuin3, SpeedWing, WhiteHat, mezzo

Threading questions

Postby mezzo » Mon Apr 21, 2008 3:16 pm

1) hmm, I'm probably doing something dumb, but just wondering is someone could shed some light on this.

Code: Select all
/////////////////////////////////////////////////////////////////////////////////////////////
VOID mainthread() {
Clear();

DWORD dwParm = 0;
ERRORCODE = 0;
int counter = 0;

HANDLE hThread = CreateThread("for_real", dwParm);

if ( !hThread ) {
   PrintF("[ERROR] Failed to create the run thread!");
   return;
   }
PrintF("[RUN] Started the run in a thread..");

while ( ERRORCODE < 1 ) {
Sleep(1000);
counter++;
if ( debugflag ) PrintF("[DEBUG] We are currently %u seconds into the run.", counter);
if (counter > 180) {
   ERRORCODE = 2;
   PrintF("Errorcode was nr 2");
   }
}
CloseHandle( hThread );

}


When debugflag is set to false, the PrintF statements inside the thread (for_real function), don't get printed until the thread is closed.
When I do set debugflag, the main loop prints a line every second and
the output generated in the thread ends up in between the debug lines.
(as I would expect it; ie during the running of the thread).
Why doesn't it output the text when the thread is running and debugflag is off ?

2) I added my 'automisation' routine in a different thread, so that I can
check from inside the thread for certain global variables.. ie bind a hotkey
to a function that sets a bool to TRUE to make the thread abort.
For some strange reason when I hit the hotkey in the middle of the thread
execution, it will only set the bool after the thread has finished..
Could anybody give me a small example of how a hotkey stops a thread?
Do I need 2 threads to accomplish this ?
- No thanks, I already have a penguin -
User avatar
mezzo
El Mariachi
 
Posts: 739
Joined: Mon Apr 30, 2007 10:27 pm
Location: Antwerp

Postby L. Spiro » Mon Apr 21, 2008 4:05 pm

#1: When text is sent to the output window from another thread it may not update immediately. This is because of Windows® and how controls (such as the text box used to display the printed text) are single-threaded; the text is sent to a waiting area and the thread may continue but the textbox can only be updated from the main thread and the holding area needs to wait for the right moment.
When the text is updated from the main thread it is pulled from the waiting area and used then. Otherwise, an update request has to be sent to the first thread (which handles both the control and the main thread of your script) and it may get blocked for a while depending on how Windows® handles threads.
I have considered adding a function to update the text box entirely.

In the meantime there is nothing you or I can do about it.

#2: Hotkeys are handled on the main MHS thread. Which means scripts that are executed via Hotkeys are run on the main MHS thread. Which means Hotkeys can not be polled again until the script finishes whatever it is doing. Hence if you use the main thread to scan for a change in a global it will never see the change until the script finishes and the main thread goes back to MHS to allow it to poll Hotkeys again.

The solution is to use the main thread to start a second thread which does all the work. The second thread does the long task that needs to be done while the main thread is in MHS polling Hotkeys (the first script thread has already exited). When a Hotkey is hit the main thread calls a script function which changes a global which is checked by the second thread.

No example needed for this simple task.


L. Spiro
Our songs remind you of songs you’ve never heard.
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby mezzo » Tue Apr 22, 2008 7:23 pm

1) fair enough, I can get the output I want to file or simple keep on using the debugflag for this purpose.

2) I think I understand.. something like the below, right ?

Code: Select all
HANDLE HNDworkthread;

bool Bstop_workthread = FALSE;

bool Bstart_run;

//////////////////////////////////////////////////////////////
void start_threads() {
HNDworkthread = CreateThread("workerthread", workparams);
if ( !HNDworkthread ) {
   PrintF("[ERROR] Failed to create the work thread!");
   return;
   }
}
//////////////////////////////////////////////////////////////
void workerthread() {
   while ( !Bstop_workthread ) {
      if ( Bstart_run ) {
         //do whatever you want done
      }
      else { Sleep(1000); }
   }
   Bstop_workthread = FALSE;
   return;
}
//////////////////////////////////////////////////////////////
void on_hk_1() {
start_threads();
}
//////////////////////////////////////////////////////////////
void on_hk_2() {
Bstart_run = TRUE;
}
//////////////////////////////////////////////////////////////
void on_hk_3() {
CloseHandle( HNDworkthread );
}
//////////////////////////////////////////////////////////////
- No thanks, I already have a penguin -
User avatar
mezzo
El Mariachi
 
Posts: 739
Joined: Mon Apr 30, 2007 10:27 pm
Location: Antwerp

Postby L. Spiro » Tue Apr 22, 2008 10:21 pm

Code: Select all

bool Bstop_workthread = FALSE;

bool Bstart_run;

//////////////////////////////////////////////////////////////
void start_threads() {
    HANDLE HNDworkthread = CreateThread("workerthread", workparams);
    if ( !HNDworkthread ) {
        PrintF("[ERROR] Failed to create the work thread!");
        return;
    }
    CloseHandle( HNDworkthread );
}
//////////////////////////////////////////////////////////////
void workerthread() {
   while ( !Bstop_workthread ) {
      if ( Bstart_run ) {
         //do whatever you want done
      }
      else { Sleep(1000); }
   }
   Bstop_workthread = FALSE;
   return;
}
//////////////////////////////////////////////////////////////
void on_hk_1() {
    start_threads();
}
//////////////////////////////////////////////////////////////
void on_hk_2() {
    Bstart_run = TRUE;
}
//////////////////////////////////////////////////////////////




L. Spiro
Our songs remind you of songs you’ve never heard.
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby mezzo » Thu Apr 24, 2008 3:53 am

I tried implementing this on my big script... but it's not working..
+ the threads are not providing me any output whatsoever, so I have no
clue what they are doing :p

will have to go back to basics and make some test proggies first to see
if what I'm doing is actually feasible.
- No thanks, I already have a penguin -
User avatar
mezzo
El Mariachi
 
Posts: 739
Joined: Mon Apr 30, 2007 10:27 pm
Location: Antwerp

Postby CoMPMStR » Sat Apr 26, 2008 10:44 pm

Shouldn't the workerthread be declared with the dwParam variable?

Code: Select all
void workerthread(DWORD dwParam)


In the helpfile, doesn't it say that the function used for CreateThread must be declared like this or the thread won't work?

The target function must be in the format DWORD [function]( DWORD dwParm ).
Image

______________________________________________________
My Utilities:
CT <-> LSSAVE Converter
LSS Visual Dialog Designer
.NET Trainer Helper Library

~Whether you think you can or you think you can't, you're right.

L. Spiro wrote:In my left hand is a red pill. If you take it I will show you the truth. I lost my right hand in the war, so I’m afraid you’re stuck with the red pill.
User avatar
CoMPMStR
(P)ot (I)n (M)y (P)ipe
 
Posts: 451
Joined: Thu Mar 06, 2008 7:50 am
Location: Best Place

Postby mezzo » Sun Apr 27, 2008 9:43 am

In all honesty, I thought that line just meant that only 1 parameter max is allowed and that it has to be a DWORD.. (so I was guessing that no parameter would be good too :p

thanks for pointing that out, will try tomorrow.
- No thanks, I already have a penguin -
User avatar
mezzo
El Mariachi
 
Posts: 739
Joined: Mon Apr 30, 2007 10:27 pm
Location: Antwerp

Postby L. Spiro » Sun Apr 27, 2008 8:55 pm

Somewhere in the help file it says that all callback functions (functions called by MHS itself directly for any reason, including Hotkey functions) can omit any unneeded parameters in order from the last to the first.
This includes the function called by CreateThread(). The parameter is optional.


L. Spiro
Our songs remind you of songs you’ve never heard.
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby mezzo » Sun May 04, 2008 10:09 am

finally figured it out.. it's all working now.
It works when I do the bool checks in full instead of short:

doesn't seem to work:
if ( run ) { //blah blah }

is working:
if ( run == TRUE ) { //more blah blah }

Perhaps because I don't declare the bools explicitly as TRUE or FALSE

Thanks for the help :-) threading rocks !
- No thanks, I already have a penguin -
User avatar
mezzo
El Mariachi
 
Posts: 739
Joined: Mon Apr 30, 2007 10:27 pm
Location: Antwerp

Postby L. Spiro » Sun May 04, 2008 11:03 am

That might indicate a minor error in the script language but right now I do not have time to look into it, and it works with the alternative anyway.


L. Spiro
Our songs remind you of songs you’ve never heard.
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby mezzo » Sun May 04, 2008 8:38 pm

Don't worry about it, writing it in full makes it more readable anyway.
- No thanks, I already have a penguin -
User avatar
mezzo
El Mariachi
 
Posts: 739
Joined: Mon Apr 30, 2007 10:27 pm
Location: Antwerp


Return to Help

Who is online

Users browsing this forum: No registered users and 0 guests

cron