this is the usage of autoresetevent in c#
An AutoResetEvent is like a ticket turnstile: inserting a ticket lets exactly one person through. The “auto” in the class’s name refers to the fact that an open turnstile automatically closes or “resets” after someone steps through. A thread waits, or blocks, at the turnstile by calling WaitOne (wait at this “one” turnstile until it opens), and a ticket is inserted by calling the Set method. If a number of threads call WaitOne, a queue builds up behind the turnstile. (As with locks, the fairness of the queue can sometimes be violated due to nuances in the operating system). A ticket can come from any thread; in other words, any (unblocked) thread with access to the AutoResetEvent object can call Set on it to release one blocked thread. You can create an AutoResetEvent in two ways. The first is via its constructor: var auto = new AutoResetEvent (false); (Passing true into the constructor is equivalent to immediately calling Set upon it.) The second way to create an AutoResetEvent is as follows: var auto = new EventWaitHandle (false, EventResetMode.AutoReset); static EventWaitHandle _waitHandle = new AutoResetEvent(false ); static void Main(string[] args) { new Thread (Waiter).Start(); Thread.Sleep(1000); // Pause for a second... _waitHandle.Set(); // Wake up the Waiter. Console.ReadLine(); } static void Waiter() { Console.WriteLine("Waiting..." ); _waitHandle.WaitOne(); // Wait for notification Console.WriteLine("Notified" ); } ************************* static EventWaitHandle _ready = new AutoResetEvent(false ); static EventWaitHandle _go = new AutoResetEvent(false ); static readonly object _locker = new object (); static string _message; static void Main(string[] args) { new Thread (Work).Start(); _ready.WaitOne(); // First wait until worker is ready lock (_locker) _message = "ooo" ; _go.Set(); // Tell worker to go _ready.WaitOne(); lock (_locker) _message = "ahhh" ; // Give the worker another message _go.Set(); _ready.WaitOne(); lock (_locker) _message = null ; // Signal the worker to exit _go.Set(); Console.ReadLine(); } static void Work() { while (true ) { _ready.Set(); // Indicate that we're ready _go.WaitOne(); // Wait to be kicked off... lock (_locker) { if (_message == null ) return; // Gracefully exit Console.WriteLine(_message); } } } ***************************** In the example below, we use a single AutoResetEvent to signal a worker, which waits when it runs out of tasks (in other words, when the queue is empty). We end the worker by enqueing a null task: To ensure thread safety, we used a lock to protect access to the Queue<string> collection. We also explicitly closed the wait handle in our Dispose method, since we could potentially create and destroy many instances of this class within the life of the application. static void Main(string[] args) { using (ProducerConsumerQueue q = new ProducerConsumerQueue()) { q.EnqueueTask( "Hello"); for (int i = 0; i < 10; i ) q.EnqueueTask("Say " i); q.EnqueueTask( "Goodbye!"); } // Exiting the using statement calls q's Dispose method, which // enqueues a null task and waits until the consumer finishes. Console.ReadLine(); } class ProducerConsumerQueue : IDisposable { EventWaitHandle _wh = new AutoResetEvent( false); Thread _worker; readonly object _locker = new object(); Queue<string > _tasks = new Queue<string >(); public ProducerConsumerQueue() { _worker = new Thread (Work); _worker.Start(); } public void EnqueueTask(string task) { lock (_locker) _tasks.Enqueue(task); _wh.Set(); } public void Dispose() { EnqueueTask( null); // Signal the consumer to exit. _worker.Join(); // Wait for the consumer's thread to finish. _wh.Close(); // Release any OS resources. } void Work() { while (true ) { string task = null ; lock (_locker) if (_tasks.Count > 0) { task = _tasks.Dequeue(); if (task == null ) return; } if (task != null ) { Console.WriteLine("Performing task: " task); Thread.Sleep(1000); // simulate work... } else _wh.WaitOne(); // No more tasks - wait for a signal } } }
Comments