class Program { static object lockObject = new object(); static void Main(string[] args) { for (int i = 0; i < 10; i++) { Thread t = new Thread(DoWork); t.Start(); } } static void DoWork() { Monitor.Enter(lockObject); try { // thread-safe code here } finally { Monitor.Exit(lockObject); } } }
class Program { static object lockObject = new object(); static bool isComplete = false; static void Main(string[] args) { Thread t1 = new Thread(Work); t1.Start(); Thread t2 = new Thread(Complete); t2.Start(); t1.Join(); } static void Work() { Monitor.Enter(lockObject); try { while (!isComplete) { Monitor.Wait(lockObject); } // code to execute after signal is received } finally { Monitor.Exit(lockObject); } } static void Complete() { Monitor.Enter(lockObject); try { // code to signal completion isComplete = true; Monitor.Pulse(lockObject); } finally { Monitor.Exit(lockObject); } } }In this example, the `Work()` method will wait for a signal from the `Complete()` method before executing code after the signal is received. This is achieved using the `Monitor.Wait()` and `Monitor.Pulse()` methods. Package library: System.Threading.