Those instructions will not be reordered, which means that, on the producing thread, the field assignment will always occur before the handle is signaled, and, on the consuming thread, the field will always be read after the handle is signaled.
If any of these two pairs of instructions could be re-ordered (e.g., if the second thread could read the field before the handle was signaled), then you would not see the correct value.
WaitOne()
introduces an implicit memory barrier, giving you the acquire-release semantics you need.
Brian Gideon and Hans Passant put together a nice list of several classes in the .NET framework that introduce implicit memory barriers: Memory barrier generators
More info: Acquire and release semantics / Acquire and release fences