I have implemented an experimental number-testing method in my program that I am currently testing out for stability. It turns out that it is not very stable at all.
From the "main" thread, responsible for drawing the GUI, you press a button. If certain check boxes are checked, it calls six different functions.
Each of these functions takes three parameters, one of which is a newly-initialized instance of a structure to which the other two parameters are passed. This function calls other functions via pointers, as these other functions are part of a structure in order to run in a separate thread.
Simply put, you call six functions and each starts a new thread.
My question has a few parts. I find myself in a strangely paradoxical situation, whereby each thread is initialized with a handle to itself that I can then pass to the SuspendThread() or TerminateThread() functions. The problem is that in order for this to make any sense, the handle is a member of the structure accessed by the thread. Thus I do it like this:
pprothstructvr1->Thread1=CreateThread(0, 0, TestProthVR1, pprothstructvr1, 0, pprothstructvr1->ProthThread1);
where "pprothstructvr1" is a parameter passed to the TestProthVR1 function - indeed this parameter is the instance of the structure initialized on the main thread.
Thread1, in this case, is a LPDWORD handle initialized such that I can then call other things using it. For instance, I have a button on the main window that, when pressed, is meant to pause or resume the number testing (that is, suspend/resume all 6 threads) like this:
void PauseProthVR1(ProthStructVR1 * pprothstructvr1)
{
SuspendThread(pprothstructvr1->Thread1);
}
void ResumeProthVR1(ProthStructVR1 * pprothstructvr1)
{
ResumeThread(pprothstructvr1->Thread1);
}
This works well enough. However, suppose I wish to cancel an in-progress test (that is, end the thread before the big intense function actually returns). I have a button called STOP that currently calls TerminateThread(handle, return code).
Being unfamiliar with multi-threading, I was unaware that TerminateThread() ought only be used, according to MSDN, in "extreme circumstances." I stupidly put TerminateThread() at the end of the functions meant to end the thread (of which there are 3).
In my experience, if I call ExitThread() or something like that, it ends the calling thread, so if I were to call that function from the main window, it would close the application and kill the main process - not helpful!
I read this at MSDN:
Quote
Now, I think I understand that. Somewhat. However, my threads are structured like this:
1. main window calls "start" function using structure name
2. "start" function passes pointers to the structure's members
3. "start" function calls CreateThread() with the "Testing" function as its starting address
4. "Testing" function does operations on/using members of the structure in a "for" loop
5. If condition X is satisfied, "Testing" function calls the "Composite" function and breaks the "for" loop
6. If condition Y is satisfied, "Testing" function calls the "Prime" function and breaks the "for" loop
7. The "Prime" and "Composite" function both do the same thing - display results and end the thread.
I'm sorry if this is complex, but thank you for bearing with me so far.
Here is the paradox I mentioned earlier (at least it seems like one to me):
In order to clean up memory, I need to delete the structure I initialized. However, if I do that before I end the thread, I am unable to pass the thread handle to the exit function. If I do that after I end the thread, it will never get deleted because the thread using the structure has already ended!
I do know about the WaitForSingleObject() function but have never used it. I am not 100% sure about thread management.
When I run my program in a Windows environment, it will carry out one test without a hitch. If I try to perform another, however, it seizes up! Running it through the Visual Studio debugger, moreover, throws AccessViolations and references KernelBase.dll without performing a single test.
My initial thinking was that setting stack size to 0 was a bad idea, as what's defined in the application header as the default stack size is almost definitely not enough. It's just that the last time I played with memory management, my little application was eating 1,7GB of RAM and accomplishing very little.
I also know that TerminateThread() is NOT what I should be calling. But then how do I cancel the test (that is, stop the thread before it returns)?
If I've opened up a can of worms with VC++ and/or Windows itself, do let me know. If there's a better way of multi-threading, I'd love to know what it is.
Thanks!

New Topic/Question
Reply



MultiQuote





|