That's correct.
The brackets
Monitor.Enter()
...
Monitor.Exit()
play the role analogues to that of
lock
statement. The expression under the
lock
or in the
lock
block implicitly bracket the code in "get lock" ... "release lock". In the same way,
Monitor.Enter
will hold all the thread in the wait queue until the thread currently owning a monitor exits, which is "already thread-safe", it
already ensures mutual exclusion operation as the lock would.
In contrast, "The Pulse, PulseAll, and Wait methods must be invoked from within a synchronized block of code." (Microsoft, see
http://msdn.microsoft.com/en-us/library/system.threading.monitor.pulse.aspx[
^]).
Look at the sample from the same help page.
One thread is feeding data in a queue, another thread is consuming the data from the same queue. As a call to
Pulse
if
a non-blocking call; and operation depends on the order of calls to
Pulse
and
Wait
. To ensure that this order of operations is not broken be the other thread's operation interlaced with the other (race condition,
http://en.wikipedia.org/wiki/Race_condition[
^]), the operations have to be done in mutually exclusive order, that is guaranteed by the lock on the same object as
Wait
and
Pulse
; this object is a queue itself. This is not a problem to re-use the queue as a data container and a lock object at the same time, because this object is
private
(not
public
or
internal
).
—SA