Tuesday, March 16, 2010

Thread.Suspend – Don’t call me anymore

Recently I ported our project from .NET 3.5 to .NET 3.5 SP1. Among the bunch of warnings, I found these interesting (to write about):-

Thread.Suspend has been deprecated. Please use other classes in System.Threading, such
as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources.
http://go.microsoft.com/fwlink/?linkid=14202

Thread.Resume has been deprecated. Please use other classes in System.Threading, such
as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources.
http://go.microsoft.com/fwlink/?linkid=14202"

I had used the Thread.Suspend and Thread.Resume APIs in order to freeze operation (interaction with hardware) until the desired user input is received to continue. This is not a rogue programming model. In the Win32 world, despite the caveats raised for SuspendThread and ResumeThread, these APIs are not uncommon for tough guys. I have used it in my earlier projects. But it seems, in .NET world, we have to infer something from the above warnings. These native and low-level APIs seem to have some serious implications. My interpretation of this warning is Microsoft is not going to support this API anymore. Since the threading and runtime infrastructure is always undergoing (internal) changes, it seems to have a strong bearing on the behavior of the API. Besides, CLR thread may not be a Win32 thread physically. I have read that the CLR may use fibers, if possible. So the CLR safely withdraws from providing any more guarantees for platform specific low-level APIs.

Now Let’s see what are the implications of using this API in our code

With Thread.Suspend, we have explicit control over the execution of an arbitrary thread which is absolutely a dangerous thing. Thread.Suspend/Resume are very primitive and low level APIs to be used control the flow of a program. A thread may be executing any piece of code when it is being suspended, It may be executing a user code or an operating system code at the User-Level IRQL or in a third-party library. Under these situations, the caller of Thread.Suspend is totally oblivious of the fact that the thread might be holding synchronization locks that are critical to the application/library and OS. This could result in deadlocks that are difficult to debug. All this is pointing towards one thing, an application is not well designed if it is using these APIs.

If we want to synchronize threads, we should always resort to understanding the problem first and design a solution with the higher primitives provided by the framework like Mutex, Semaphores, critical sections and events etc; that is what is suggested by .NET with the above warnings. By using these high-level primitives, we delegate the lower-level responsibilities of suspending and resuming the threads to the Framework/OS. Besides making our code safe, we make our intent explicit. A few lines of explicit code is worth a ton of documentation!

No comments:

Post a Comment