Thread.Suspend()

R

Robert Speck

Hi there,

Can anyone shed anymore light on why "Thread.Suspend()" has been deprecated
by MSFT beyond what MSDN says about it. I'm not sure if I quite appreciate
the various pitfalls they discuss but using it under certain circumstances
still seems reasonable. For instance, I want to display a small modal dialog
with a "Cancel" button which allows the user to abort a background thread.
If the user clicks this button, I then want to prompt them to confirm the
cancellation. While the confirmation dialog is on-screen however, I want to
suspend the background thread until the user makes their decision. Is this
considered a dangerous approach however. The only other alternative I can
think of is to have my background thread periodically inspect some event
object (say, "AutoResetEvent") which the main GUI thread can [re]set as
required (the background thread will then start and stop accordingly). This
is an unwieldy approach IMO however and it also allows the background thread
to briefly continue its work until it gets around to checking the event. Any
comments would be appreciated. Thanks.
 
N

Nicholas Paldino [.NET/C# MVP]

Reobert,

Basically, it is no longer guaranteed that a Thread object corresponds
to an operating system thread. The Thread class represents a logical
thread, and making calls to Abort, Suspend, etc etc can have unexpected side
effecs on your code when the Thread class doesn't map one to one to an OS
thread.

Hope this helps.
 
R

Robert Speck

Basically, it is no longer guaranteed that a Thread object corresponds
to an operating system thread. The Thread class represents a logical
thread, and making calls to Abort, Suspend, etc etc can have unexpected
side effecs on your code when the Thread class doesn't map one to one to
an OS thread.

Thanks for the feedback. I find this layer of abstraction counterintuitive
however :) From a programmer's perspective a thread is a thread and you
should be able to pause it at will provided it's not dangerous to do so at
the time (which should be the programmer's responsibility). No doubt there
are deeper technical reasons but on the surface this situation makes life
more difficult (obfuscating what should otherwise be a simple mechanism - at
the very least the OS should be able to safely pause a thread at its
earliest opportunity). Anyway, thanks again.
 
N

Nicholas Paldino [.NET/C# MVP]

While you might find it counterintuitive, from the framework
perspective, it's right. The CLR can be hosted in many different
environments, and it gives those environments the opportunity to control and
schedule threads that are used to execute tasks in the CLR. It's because of
this that the abstraction exists. This is new to 2.0, which is why they
those methods are marked as obsolete now.

And to be completely honest, suspending your thread does little for you.
Yes, you keep the work from proceeding, but the work needs to be broken up
into what are considered atomic units. If you are in the middle of
performing work in one of those units, you should be rolling back that work,
so as to not leave your program in an inconsistent state.

If you are not using a transaction manager to manage that state, and
don't have a means by which to roll it back, it doesn't matter if the task
completes or does not. Inconsistent state is inconsistent state.

Using the event and the property isn't that big of a deal, really.
Basically, you would have a ManualResetEvent and a boolean flag:

private ManualResetEvent waitEvent = new ManualResetEvent();
private bool continue = true;

Before you start the thread, you set the event:

waitEvent.Set();

Then, you have this function:

private bool CheckCancel()
{
// Wait on the event.
waitEvent.WaitOne();

// Return the cancel flag.
return !continue;
}

When you cancel, set the flag to false, and call Reset on the handle.
This can all be wrapped up in a tidy little class as well.

As for it being counterintuitive, I can only say I disagree. Using OS
thread mechanisms to control program flow has always been a very bad thing
for me.
 
R

Relaxin

As for it being counterintuitive, I can only say I disagree. Using OS
thread mechanisms to control program flow has always been a very bad thing
for me.
It may have been bad for YOU, but it was great for me.

The more deeper I get into .NET 2.0, the more a start to hate it.
 
W

Willy Denoyette [MVP]

| Hi there,
|
| Can anyone shed anymore light on why "Thread.Suspend()" has been
deprecated
| by MSFT beyond what MSDN says about it. I'm not sure if I quite appreciate
| the various pitfalls they discuss but using it under certain circumstances
| still seems reasonable. For instance, I want to display a small modal
dialog
| with a "Cancel" button which allows the user to abort a background thread.
| If the user clicks this button, I then want to prompt them to confirm the
| cancellation. While the confirmation dialog is on-screen however, I want
to
| suspend the background thread until the user makes their decision. Is this
| considered a dangerous approach however. The only other alternative I can
| think of is to have my background thread periodically inspect some event
| object (say, "AutoResetEvent") which the main GUI thread can [re]set as
| required (the background thread will then start and stop accordingly).
This
| is an unwieldy approach IMO however and it also allows the background
thread
| to briefly continue its work until it gets around to checking the event.
Any
| comments would be appreciated. Thanks.
|
|

It's been deprecated because it builds upon the Win32 API "SuspendThread".
It's an API which should never have existed in the CLR (just like
Thread.Abort for that matter) simply because the underlying API's should
never be called from user code, take a look at the "Remarks" in MSDN, here
is a snip from SuspendThread...

< .. This function is primarily designed for use by debuggers. It is not
intended to be used for thread synchronization. Calling SuspendThread on a
thread that owns a synchronization object, such as a mutex or critical
section, can lead to a deadlock if the calling thread tries to obtain a
synchronization object owned by a suspended thread. To avoid this situation,
a thread within an application that is not a debugger should signal the
other thread to suspend itself. The target thread must be designed to watch
for this signal and respond appropriately.
/>

1. ...designed for use by debuggers..
2. ...not intended to be used for thread synchronization.
3. ... can lead to a deadlock
4. ... an application that is not a debugger should signal the other thread
to suspend itself...

These API's are dangerous, especially when called from a higly virtualized
environment like the CLR, your calling thread and the CLR never knows
exactly what a thread is doing when executing "unmanaged" code.
Really, when you need to suspend a thread, you should do what is apply 4
(see above), use a sychronization primitive to signal another thread to
suspend/resume itself.

Willy.
 
J

Jon Skeet [C# MVP]

It may have been bad for YOU, but it was great for me.

That suggests to me that you may well just not have come across any of
the problems of arbitrarily suspending (or aborting) threads. The code
of a thread generally knows where it is safe to suspend or exit. As
another thread is very unlikely to know *exactly* what the first thread
is doing, it is in a much worse position to make those judgements.

Suspending threads can so, so easily cause deadlocks etc. It's a really
bad idea, just like killing other threads with Thread.Abort is a bad
idea unless you're about to terminate the whole app. It's easy to use
badly, but *insanely* difficult to use really, really safely.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top