ThreadBoard ArchivesSite FeaturesActiveworlds SupportHistoric Archives |
Multithreading Tutorial (Was to be "Is there a wait command?") (Sdk)
Multithreading Tutorial (Was to be "Is there a wait command?") // Sdko0oiiijoshiiio0oJul 17, 2002, 10:34am
Multithreading is a good thing. I'll give you some code to get you started,
but be warned that my code actually only waits 5 between saying it will wait 5 and saying it has waited 5 - it won't stop its other actions from running. Excersise for the student, not the woke-up-10-minutes-ago teacher ;) #include <windows.h> #include <aw.h> #include <time.h> HANDLE d_ThreadHandle; DWORD d_threadID; bool d_IsRunning; int StartTime; int TimeToFinish; void TimerStarter() { aw_say("Behold, as I wait a marvelous 5 seconds!"); // Check to make sure a handle doesn't already exist. if(d_ThreadHandle) { return; } // Create the thread to run immediately. TimerTimer is the actual procedure d_ThreadHandle = CreateThread(NULL, 0, (unsigned long (_stdcall*)(void*))TimerTimer, 0, 0, (LPDWORD)&d_threadID); if(d_ThreadHandle) { // An error occured. GetError will return a DWORD that you can look up on msdn.microsoft.com } d_IsRunning = true; // StartTime = ??? I still don't have my K&R at my desk, but look up time.h // TimeToFinish = StartTime + <5 seconds. Implement this depending on which // member of the time_t you just used a second ago> } DWORD WINAPI TimerTimer() { // This is the thread procedure function. Think main() for the thread. //int CurrentTime = <make this identical to the StartTime = from before> if(TimeToFinish - CurrentTime <= StartTime) TimeFinish(); return 0; } void TimeFinish() { // Called when our 5 seconds are up aw_say("Tada! 5 seconds!"); d_IsRunning = false; CloseHandle(d_ThreadHandle); // Normally we'd use WaitForSingleObject, but // we know because this function was called, it's done. d_ThreadHandle = NULL; } Now you can call TimeStart() from your main thread, and there'll be 5 seconds between one message and the next (but it won't actually stop the rest of your program). Shamus told me that the SDK isn't thread safe but single instance programs should be fine, so..... keep that in mind. Check d_IsRunning to see if the thread has finished yet... Ask me if you need help with actually understanding the concept of threads... Another important thing is thread safety. To show the necessity... Take, for example, a program that has two functions that create threads: FindObjectInList DeleteEntireList and they're designed to manipulate your linked list (Aww, come on, surely you know how to do that. They're so much fun! ::shrugs:: ask me if not). However, if you call DeleteEntireList, and then FindObjectInList, FindObjectInList may traverse right onto an empty pointer, thus creating a serious problem... Actually, probably a crash of your program. What you need is a Mutex (Mutual Exclusivity Operator, or something like that). Mutex's are like those red-and-green lights on the railroad tracks. They say, ok, now it's safe for one guy to go, now it's safe for the other. As long as you aren't playing with the same toys at the same time, sharing can be fun. I'm not actually going to give you code beyond copy-pasting from something of mine that's only a slight modification on elsewhere's code. I have two functions, one for a blocking mutex and one for a non-blocking mutex. I'm gunna give you the blocking mutex. Works simple: For your valuable data (like your list) you make an instance of the mutex. Whenever you need to access it, you call MutexOn();... If it is off, it's turned on and now you can access the data. If it is turned on, it stops you from going (that's the blocking part) until the other guy calls MutexOff, at which point you're good to access the data. When you're done, you call MutexOff();. class cMonitor { HANDLE d_mutex; public: cMonitor() { // This mutex will help the two threads share their toys. d_mutex = CreateMutex( NULL, false, NULL ); if( d_mutex == NULL ) throw cError( "cMonitor::cMonitor() - Mutex creation failed." ); } virtual ~cMonitor() { if( d_mutex != NULL ) { CloseHandle( d_mutex ); d_mutex = NULL; } } void MutexOn() const { WaitForSingleObject( d_mutex, INFINITE ); // To be safe... } void MutexOff() const { ReleaseMutex( d_mutex ); // To be safe... } } -J [View Quote] faberAug 1, 2002, 6:57pm
"o0oiiijoshiiio0o" <joshua_trask at capecod.com> schrieb im Newsbeitrag news:3d356465 at server1.Activeworlds.com...
> DWORD WINAPI TimerTimer() > { > // This is the thread procedure function. Think main() for the thread. > //int CurrentTime = <make this identical to the StartTime = from before> > > if(TimeToFinish - CurrentTime <= StartTime) > TimeFinish(); > > return 0; > } > I just had to comment on this: If this is your ThreadFunction, your thread won't wait 5 seconds. It will determine that 5 seconds are not yet over and exit. I am not sure about your time calculation, so it might even call TimeFinish() but not after 5 seconds but immediately. There is no loop in there or Sleep() or Waitxxx() which would cause the thread to spend some time anywhere. - Faber faberAug 1, 2002, 6:58pm
[View Quote]
This one can be accomplished by using the function Sleep() unless your bot has a GUI, which complicated things. use Sleep(5000); to wait 5 seconds. - Faber o0oiiijoshiiio0oAug 1, 2002, 8:39pm
Ahahah. Yeah. That was stoooopid of me. Well, it should have a loop that
checks the difference and calls the finisher once there is none... Oops. -J [View Quote] |