Re: problems in pausing and resumig threads
Dear Kunal,
Hi,
On Feb 27, 1:08 am, kunal s patel
<kunalspa...@discussions.microsoft.com> wrote:
I am still having problems with it......and i m not able to understand what
is wrong where......now i am writing the code u suggested in my application
and run it then it works fine but now i start this application using
CreateProcessAsUser api then the code doesn't execute......i mean it forks a
new thread but blocks the execution of code into that function. My procedure
code looks something like this
void procedure()
{
while(1)
{
while(::WaitForSingleObject(pmain->hEvent,INFINITE)==WAIT_OBJECT_0)
{
// do some processing
}
}
}
There may be something wrong in your code, because your code only
simulates one simulation step, and then it waits for the event to be
signaled, and again and again. I don't think that's what you want. I
can suggest you another way of doing this. You can define a boolean
variable like this:
volatile bool bThreadStop = false;
Notice that the "volatile" is mandatory since you should use atomic
comparisons here and the variable should not be affected with
optimizations. Then you can write your thread like this:
void ThreadProc()
{
while( 1 )
{
if( bThreadStop == true )
{
::WaitForSingleObject(hEvent, INFINIT); // wait for user
to allow execution again.
::ResetEvent(hEvent);// if you are not using manual-reset
event you can omit this line.
}
else
{
//Do simulation code, you should notice that you should
NOT create the simulation loop here, that while(1) above is the
simulation loop.
}
}
}
void Suspend()
{
bThreadStop = true;
}
void Resume()
{
bThreadStop = false; //it's better to be first, if you want to avoid
bugs.
::SetEvent(hEvent);
}
That's the code I would write. Also you should be careful because here
when you set the event it means to CONTINUE the execution after the
pause, the event here does NOT mean to suspend execution. since the
variable "bThreadStop" is volatile and you can set it while in
different threads, then you don't have to worry about compiler
optimizations. Just be sure when you resume the thread you set the
"bThreadStop" to "false" as I did here.
Also I can give you another solution, and that is to use a critical
section. First create a global variable with type CRITICAL_SECTION.
Suppose it's name is "mycs".
you can use it like this in your simulation thread loop:
while(1)
{
BOOL result = ::TryEnterCriticalSection(&mycs);
if( result != 0 )
{
::LeaveCriticalSection(&mycs);
// do your simulation loop body here.
}
else
{
//if the critical section is not owned by this thread, then it
waits until the owner releases it's ownership.
::EnterCriticalSection(&mycs);
::LeaveCriticalSection(&mycs);
}
}
void Suspend()
{
::EnterCriticalSection(&mysc);
}
void Resume()
{
::LeaveCriticalSection(&mysec);
}
also don't forget to execute this before anything:
::InitializeCriticalSection(&mycs);
The first way is much faster that the second, because the second one
needs too many context switches, and I recommend you to be careful
with the second code because I don't know what happens if the user
clicks on the suspend or resume buttons more than one time, so make
sure user can't do that.
Now when i comment out the WaitForSingleObject while loop statement, it
works fine evenwith CreateProcessAsUser but as soon as i uncomment it, it
stops working
I guess there is some problem with the rights. The user under whose account
i am runing the process does not have any access rights.....do i need to add
some right to the account or it is something else
I don't think it has anything to do with user rights, since you are
not using shared or privileged resources.
kunal
kunal s patel wrote:
Also there is one other thing that i would like to mention......the code in
procedure method has a infinite loop.....so what exactly i want is if too
much CPU is uitilized then user should be able to pause the thread and then
if he wishes to resume the thread, he can resume it from the same state....is
it possible to do so with events??
kunal
Easy. Just put a call into the infinite loop.
void procedure()
{
while (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0)
//some exection code
}
Use a manual reset event. The main thread calls SetEvent to permit the
worker thread to run. When the main thread uses ResetEvent the worker
thread will be suspended the next time it calls WaitForSingleObject.
In practice, you should actually use WaitForMultipleObjects, with
another event used to tell the thread to exit at program shutdown.
--
Scott McPhillips [VC++ MVP]
I hope these ways help you. And try to read articles about
synchronization (specially MSDN), because this kind of programming is
really tricky.
Yours,
Kourosh.