Free mag vol1 | Page 782

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