CHAPTER 19 MULTITHREADED, PARALLEL, AND ASYNC PROGRAMMING
Finally, if you want to test two values for equality and change the point of comparison in a threadsafe manner, you are able to leverage the Interlocked.CompareExchange() method as follows:
public void CompareAndExchange()
{
// If the value of i is currently 83, change i to 99.
Interlocked.CompareExchange(ref i, 99, 83);
}
Synchronization Using the [Synchronization] Attribute
The final synchronization primitive examined here is the [Synchronization] attribute, which is a
member of the System.Runtime.Remoting.Contexts namespace. In essence, this class-level attribute
effectively locks down all instance member code of the object for thread safety. When the CLR allocates
objects attributed with [Synchronization], it will place the object within a synchronized context. As you
might recall from Chapter 17, objects that should not be removed from a contextual boundary should
derive from ContextBoundObject. Therefore, if you want to make the Printer class type thread safe
(without explicitly writing thread-safe code within the class members), you could update the definition
as follows:
using System.Runtime.Remoting.Contexts;
...
// All methods of Printer are now thread safe!
[Synchronization]
public class Printer : ContextBoundObject
{
public void PrintNumbers()
{
...
}
}
In some ways, this approach can be seen as the lazy way to write thread-safe code, given that you
are not required to dive into the details about which aspects of the type are truly manipulating threadsensitive data. The major downfall of this approach, however, is that even if a given method is not
making use of thread-sensitive data, the CLR will still lock invocations to the method. Obviously, this
could degrade the overall functionality of the type, so use this technique with care.
Programming with Timer Callbacks
Many applications have the need to call a specific method during regular intervals of time. For example,
you might have an application tha