Type Reason ArgumentNullException obj is null.
Use Enter to acquire the System.Threading.Monitor on the object passed as the parameter. If another thread has executed an Enter on the object but has not yet executed the corresponding Monitor.Exit(object), the current thread will block until the other thread releases the object. It is legal for the same thread to invoke Enter more than once without it blocking; however, an equal number of Exit calls must be invoked before other threads waiting on the object will unblock.
Use System.Threading.Monitor to lock objects (that is, reference types), not value types. When you pass a value type variable to Enter, it is boxed as an object. If you pass the same variable to Enter again, it is boxed as a separate object, and the thread does not block. In this case, the code that Monitor is supposedly protecting is not protected. Furthermore, when you pass the variable to Exit, still another separate object is created. Because the object passed to Exit is different from the object passed to Enter, Monitor throws System.Threading.SynchronizationLockException. For more information, see the conceptual topic [<topic://cpconMonitor>].
Use a C# try…finally block (Try…Finally in Visual Basic) to ensure that you release the monitor, or use the C# lock statement (SyncLock statement in Visual Basic), which wraps the Monitor.Enter(object) and Monitor.Exit(object) methods in a try…finally block.