By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,865 Members | 1,365 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,865 IT Pros & Developers. It's quick & easy.

Thread.Resume is Obsolete? How are we supposed to wake up SleepingThreads now?

P: n/a
I have a thread that sleeps for 5 minutes once it's finished running a
method and then it repeats itself if it's supposed to (bool = true).
Prior to 2.0 I was able to resume the thread after marking the bool to
false which would cause the thread to finish what it was doing and
complete, or to wake up for it's sleep state and not loop back into
itself anymore.

How do we tell a thread to stop sleeping now that Thread.Resume is obsolete?
Dec 5 '05 #1
Share this Question
Share on Google+
17 Replies


P: n/a
Benny Raymond wrote:
I have a thread that sleeps for 5 minutes once it's finished running a
method and then it repeats itself if it's supposed to (bool = true).
Prior to 2.0 I was able to resume the thread after marking the bool to
false which would cause the thread to finish what it was doing and
complete, or to wake up for it's sleep state and not loop back into
itself anymore.

How do we tell a thread to stop sleeping now that Thread.Resume is obsolete?


You use Monitor.Wait/Pulse or WaitHandles, which is what you should
have been doing before :)

See http://www.pobox.com/~skeet/csharp/t...eadlocks.shtml (half
way down) for a sample of this.

Jon

Dec 5 '05 #2

P: n/a
Also dont use Thread::Suspend().
http://joehacker.blogspot.com/2005/1...nd-method.html

Ab.
http://joehacker.blogspot.com

"Benny Raymond" <be***@pocketrocks.com> wrote in message
news:O2****************@TK2MSFTNGP14.phx.gbl...
I have a thread that sleeps for 5 minutes once it's finished running a
method and then it repeats itself if it's supposed to (bool = true).
Prior to 2.0 I was able to resume the thread after marking the bool to
false which would cause the thread to finish what it was doing and
complete, or to wake up for it's sleep state and not loop back into
itself anymore.

How do we tell a thread to stop sleeping now that Thread.Resume is

obsolete?
Dec 6 '05 #3

P: n/a
That's fine, however the thing you showed me is still sleeping - I need
to be able to wake up the sleeping thread, or terminate it (is that when
abort comes into play?)

Basically what I need to do is this:

* ClientA needs to be run every 5 minutes
* If SettingX changes to false, it allows ClientA to finish running
(if it's currently running) but it will no longer run again.
* If SettingX changes to true, it tells ClientA to start back up on
it's 5 minute cycle again.
* If App closes, it allows ClientA to finish running (if it's
currently running) but it will no longer run again.

What I was doing before (which I can see why it's wrong now but not how
to do it correctly):
* ClassX creates ClientA class
* ClassX sets loop_bool in ClientA to true
* ClassX starts ClientA thread
* ClientA thread runs and sleeps at the end
* When ClientA is done sleeping it loops, checks the loop_bool and
continus running if loop_bool is true.
* SettingX in ClassX changes
* ClassX sets loop_bool in ClientA to false
* ClassX Resumes ClientA thread
* ClassX Joins ClientA
* ClientA finishes and doesn't loop
* ClassX checks setting to see if it's true, if so it starts up the
ClientA thread again
Please help me.. haha :)

~Benny
Jon Skeet [C# MVP] wrote:
Benny Raymond wrote:
I have a thread that sleeps for 5 minutes once it's finished running a
method and then it repeats itself if it's supposed to (bool = true).
Prior to 2.0 I was able to resume the thread after marking the bool to
false which would cause the thread to finish what it was doing and
complete, or to wake up for it's sleep state and not loop back into
itself anymore.

How do we tell a thread to stop sleeping now that Thread.Resume is obsolete?

You use Monitor.Wait/Pulse or WaitHandles, which is what you should
have been doing before :)

See http://www.pobox.com/~skeet/csharp/t...eadlocks.shtml (half
way down) for a sample of this.

Jon

Dec 6 '05 #4

P: n/a
Benny Raymond wrote:
That's fine, however the thing you showed me is still sleeping - I need
to be able to wake up the sleeping thread, or terminate it (is that when
abort comes into play?)


You need to look through the example more carefully. The *producing*
thread is sleeping - the *consuming* thread is waiting.

The producing thread is only sleeping in order to simulate "things
happening" (processing, whatever). It's unimportant from the example's
point of view. Wait/Pulse is the important part here - you can give a
timeout to Wait, so that it will return either when the timeout has
elapsed or when the monitor is pulsed.

Jon

Dec 6 '05 #5

P: n/a
So what you're saying is that I should use Wait as if I was using Sleep
- and use Pulse to wake that Wait state up? That brings me to another
question however which is, how can I make sure that the thread is
Waiting before I pulse it, and how can I make sure the pulse gets there
in that circumstance? Hopefully this is clear if you look at the steps
I posted prior to your last message?

Jon Skeet [C# MVP] wrote:
Benny Raymond wrote:
That's fine, however the thing you showed me is still sleeping - I need
to be able to wake up the sleeping thread, or terminate it (is that when
abort comes into play?)

You need to look through the example more carefully. The *producing*
thread is sleeping - the *consuming* thread is waiting.

The producing thread is only sleeping in order to simulate "things
happening" (processing, whatever). It's unimportant from the example's
point of view. Wait/Pulse is the important part here - you can give a
timeout to Wait, so that it will return either when the timeout has
elapsed or when the monitor is pulsed.

Jon

Dec 6 '05 #6

P: n/a
Nevermind, I looked back over it again with a clean head and it's only
waiting if nothing is in the queue, which means that if I pulse it after
adding to the queue things will be ok... So if you don't mind could you
look at this pseudo code for me?

class clientMonitor
{
myClient is a "client" from class client

function main
{
initialize myClient
if (run_client_global_setting is true) then myClient.Run
}

function updateClient (gets called in cases when
run_client_global_setting changes, or main form closes, etc)
{
if (run_client_global_setting is true) then
set myClient.keep_running to true
else
set myClient.keep_running to false

Lastly run the function client.Run
}
}

class client
{
locker is a readonly object
queue is a Queue
keep_running is a boolean

function Run (something)
{
Lock the listLock object
add object "something" to Queue stack
if queue's count == 1, pulse locker
Unlock listlock object
}

function client_runner
{
loop if keep_running is true
{
Run client function that takes a few seconds to complete, then...

Lock the listLock object
if the queue has no items in it, Wait on listlock until pulsed
or until 5 minutes is up
Unlock listlock object
}
}

}



Benny Raymond wrote:
So what you're saying is that I should use Wait as if I was using Sleep
- and use Pulse to wake that Wait state up? That brings me to another
question however which is, how can I make sure that the thread is
Waiting before I pulse it, and how can I make sure the pulse gets there
in that circumstance? Hopefully this is clear if you look at the steps
I posted prior to your last message?

Jon Skeet [C# MVP] wrote:
Benny Raymond wrote:
That's fine, however the thing you showed me is still sleeping - I need
to be able to wake up the sleeping thread, or terminate it (is that when
abort comes into play?)


You need to look through the example more carefully. The *producing*
thread is sleeping - the *consuming* thread is waiting.

The producing thread is only sleeping in order to simulate "things
happening" (processing, whatever). It's unimportant from the example's
point of view. Wait/Pulse is the important part here - you can give a
timeout to Wait, so that it will return either when the timeout has
elapsed or when the monitor is pulsed.

Jon

Dec 6 '05 #7

P: n/a
is Monitor.Pulse actually like a enqueue and Monitor.Wait like a dequeue
except that if you give it a timeout it doesn't dequeue?

Jon Skeet [C# MVP] wrote:
Benny Raymond wrote:
That's fine, however the thing you showed me is still sleeping - I need
to be able to wake up the sleeping thread, or terminate it (is that when
abort comes into play?)

You need to look through the example more carefully. The *producing*
thread is sleeping - the *consuming* thread is waiting.

The producing thread is only sleeping in order to simulate "things
happening" (processing, whatever). It's unimportant from the example's
point of view. Wait/Pulse is the important part here - you can give a
timeout to Wait, so that it will return either when the timeout has
elapsed or when the monitor is pulsed.

Jon

Dec 6 '05 #8

P: n/a
Ok... after some more messing around with it i've come up with this...
Do I still have the wrong idea?

Class A
{
// non related threading stuff....
// at some point
B _client = new B();
Thread _clientThread = null;
// end non related threading stuff...

public void RunMacro()
{
if (_prefrences.Enable)
{
StopMacro(); // stop just incase we're currently running.
_clientThread = new Thread(new ThreadStart(_client.ClientThead));
_clientThread.Name = "ClientThread " +
_clientThread.ManagedThreadId.ToString();
_clientThread.Start();
}
}

public void StopMacro()
{
try
{
if (_clientThread != null &&
_clientThread.ThreadState ==
System.Threading.ThreadState.Running)
{
// tell it not to run anymore
_client.KEEP_RUNNING = false;

// Add a pulse just to make sure it stops waiting
_client.PulseClient();

// join and let it finish running
_clientThread.Join();
}
}
catch (Exception) { }
}
}

Class B
{
// more code unrelated
// at some point:
public bool KEEP_RUNNING = false;
private readonly object locker = new object();
// end more code unrelated

public void PulseClient()
{
lock (locker)
{
Monitor.Pulse(locker);
}
}

public void ClientThead()
{
int i = 5 * 60 * 1000;
lock (locker)
{
while (KEEP_RUNNING)
{
if (_prefrences.Enable)
{
// RunClient will return 5min or 20min
i = RunClient();
}
Monitor.Wait(locker, i);
}
}
}

private int RunClient()
{
// do a bunch of stuff...
if ({some expression})
return 5 * 60 * 1000;
else
return 20 * 60 * 1000;
}
}
Dec 6 '05 #9

P: n/a
Benny Raymond <be***@pocketrocks.com> wrote:
is Monitor.Pulse actually like a enqueue and Monitor.Wait like a dequeue
except that if you give it a timeout it doesn't dequeue?


If anything, it's the other way round - you *could* think of
Monitor.Wait as adding a thread to a queue of threads to be pulsed,
although I don't believe the ordering of pulsing is guaranteed.

It's not a terribly helpful way of thinking about it though. Think of
it as a thread watching a reference to see when a light goes on (or
something like that). Pulse flashes that light.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 7 '05 #10

P: n/a
Benny Raymond <be***@pocketrocks.com> wrote:
Ok... after some more messing around with it i've come up with this...
Do I still have the wrong idea?


<snip>

No, that's mostly correct. A few problems though:

1) KEEP_RUNNING needs to be volatile, or you need to lock access to it.
See http://www.pobox.com/~skeet/csharp/t...latility.shtml for
more details on that.

2) Don't use _clientThread.ThreadState - just join the thread if it's
non-null.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 7 '05 #11

P: n/a
The ordering of pulsing isn't guaranteed, but is the fact that a pulse
went out and hasn't been recieved yet guaranteed? Since I'm only using
two threads, one that waits and one that pulses wouldn't it be ok to
assume that every time I pulse, the wait block is going to hit it at
some point? The reason I ask this is that I need to pulse without
knowing where the client thread is, and if it's not waiting I don't want
it to wait once it gets to the waiting state (since i've already pulsed it).

Does that all make sense?

BTW: thanks a ton - app is already running a lot better.

Jon Skeet [C# MVP] wrote:
Benny Raymond <be***@pocketrocks.com> wrote:
is Monitor.Pulse actually like a enqueue and Monitor.Wait like a dequeue
except that if you give it a timeout it doesn't dequeue?

If anything, it's the other way round - you *could* think of
Monitor.Wait as adding a thread to a queue of threads to be pulsed,
although I don't believe the ordering of pulsing is guaranteed.

It's not a terribly helpful way of thinking about it though. Think of
it as a thread watching a reference to see when a light goes on (or
something like that). Pulse flashes that light.

Dec 7 '05 #12

P: n/a
Ok... just changed that in the code as well...

Jon Skeet [C# MVP] wrote:
Benny Raymond <be***@pocketrocks.com> wrote:
Ok... after some more messing around with it i've come up with this...
Do I still have the wrong idea?

<snip>

No, that's mostly correct. A few problems though:

1) KEEP_RUNNING needs to be volatile, or you need to lock access to it.
See http://www.pobox.com/~skeet/csharp/t...latility.shtml for
more details on that.

2) Don't use _clientThread.ThreadState - just join the thread if it's
non-null.

Dec 7 '05 #13

P: n/a
Benny Raymond wrote:
The ordering of pulsing isn't guaranteed, but is the fact that a pulse
went out and hasn't been recieved yet guaranteed? Since I'm only using
two threads, one that waits and one that pulses wouldn't it be ok to
assume that every time I pulse, the wait block is going to hit it at
some point? The reason I ask this is that I need to pulse without
knowing where the client thread is, and if it's not waiting I don't want
it to wait once it gets to the waiting state (since i've already pulsed it).


If you pulse when no thread is waiting, it's a no-op. That's the big
difference between a monitor and a semaphore. If you need that kind of
behaviour, you should look at ManualResetEvent and AutoResetEvent
instead.

Jon

Dec 7 '05 #14

P: n/a
I'm looking into AutoRaiseEvent and it seems like I only have to change
a couple lines of code - however when I give a timeout to the .WaitOne
it requires an exit context... What does it all mean?
"exitContext
true to exit the synchronization domain for the context before the wait
(if in a synchronized context), and reacquire it afterward; otherwise,
false.
"

Jon Skeet [C# MVP] wrote:
Benny Raymond wrote:
The ordering of pulsing isn't guaranteed, but is the fact that a pulse
went out and hasn't been recieved yet guaranteed? Since I'm only using
two threads, one that waits and one that pulses wouldn't it be ok to
assume that every time I pulse, the wait block is going to hit it at
some point? The reason I ask this is that I need to pulse without
knowing where the client thread is, and if it's not waiting I don't want
it to wait once it gets to the waiting state (since i've already pulsed it).

If you pulse when no thread is waiting, it's a no-op. That's the big
difference between a monitor and a semaphore. If you need that kind of
behaviour, you should look at ManualResetEvent and AutoResetEvent
instead.

Jon

Dec 7 '05 #15

P: n/a
Benny Raymond <be***@pocketrocks.com> wrote:
I'm looking into AutoRaiseEvent and it seems like I only have to change
a couple lines of code - however when I give a timeout to the .WaitOne
it requires an exit context... What does it all mean?
"exitContext
true to exit the synchronization domain for the context before the wait
(if in a synchronized context), and reacquire it afterward; otherwise,
false.
"


Unless you're using synchronization domains explicitly (and unless you
know you are, you aren't!) you can just pass in false.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 7 '05 #16

P: n/a
Great... Ok, so this is what i'm doing now (one of the many places - i
went through today and fixed all of the areas where I was using threads
wrong). Let me know if I've finally got the right idea?
Class A
{
// stuff not needed...
// at some point _client is Class B
// On to the threading stuff:

public override void RunMacro()
{
if (_prefrences.Enable)
{
StopMacro(); // stop just incase we're currently running.

_client.KEEP_RUNNING = true;
_clientThread = new Thread(new ThreadStart(_client.ClientThead));
_clientThread.Name = "Taskulon5000 ClientThread " +
_clientThread.ManagedThreadId.ToString();
_clientThread.Start();
_client.SignalClient();
}
}

public override void StopMacro()
{
try
{
_client.KEEP_RUNNING = false; // tell it not to run anymore
if (_clientThread != null &&
(_clientThread.ThreadState == System.Threading.ThreadState.Running ||
_clientThread.ThreadState ==
System.Threading.ThreadState.WaitSleepJoin))
{
_client.SignalClient(); // Add a signal to make sure it stops waiting
_clientThread.Join(); // join and let it finish running
}
}
catch (Exception) { }
}
}
Class B
{
public volatile bool KEEP_RUNNING = false;
private AutoResetEvent autoEvent;
// other stuff...
// then..
public void SignalClient()
{
Debug.WriteLine("SignalClient");
autoEvent.Set();
}

public void ClientThead()
{
Debug.WriteLine("ClientThead");
int i = 5;
while (KEEP_RUNNING)
{
Debug.WriteLine(string.Format("Will wait {0} milliseconds", i),
"ClientThead");
bool a = autoEvent.WaitOne(i, false);
Debug.WriteLine(string.Format("Finished Waiting based on: {0}",
a ? "Signaled" : "Timeout"), "ClientThead");
if (_prefrences.Enable && KEEP_RUNNING)
{
i = RunClient();
}
else
{
KEEP_RUNNING = false;
}
}
}
}
Dec 7 '05 #17

P: n/a
Benny Raymond <be***@pocketrocks.com> wrote:
Great... Ok, so this is what i'm doing now (one of the many places - i
went through today and fixed all of the areas where I was using threads
wrong). Let me know if I've finally got the right idea?


<snip>

Sorry it's been so long.

1) I still wouldn't use the ThreadState to test whether it's running or
not. Just Join the thread - if it's finished, the call will just return
immediately, and signalling the client isn't going to cause any
problems.

2) I wouldn't have KEEP_RUNNING as a public field - I'd make it a
property. I'd also try to use the normal .NET naming conventions

3) Catching Exception and not doing anything with it is almost always a
bad idea - if something goes wrong, you won't have any record of it. At
the very least, log it somewhere.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 12 '05 #18

This discussion thread is closed

Replies have been disabled for this discussion.