"Producer/Consumer Example"

private static void ProducerThreadEntry() {
	while (queueRunning) {
		byte[] data = ReceiveWholeMessageFromStream();
		IMessage message = DeserializeMessage(data);
		lock (producerConsumerLock) {
			messageQueue.Enqueue(message);	
			Monitor.Pulse(producerConsumerLock);
		}
	}
}
private static void ConsumerThreadEntry() {
	IMessage message;

	while (queueRunning) {
		lock (producerConsumerLock) {
			while (messageQueue.Count == 0) {
				if (!queueRunning) return;
				Monitor.Wait(producerConsumerLock);
			}
			message = messageQueue.Dequeue();
		}
		DispatchMessage(message);
	}
}


Code snippet taken from "Common Multithreading Mistakes in C# - II: Unnecessary Contention".