ManualResetEvent detailed
ManualResetEvent allows threads to communicate with each other by signaling. Typically, this communication involves a task that a thread must complete before other threads do so. When a thread starts an activity that must be completed before other threads can start, it calls Reset to put ManualResetEvent in a non-signaled state, which can be considered a control ManualResetEvent. The thread that calls the WaitOne on the ManualResetEvent will block and wait for the signal. When the control thread completes the activity, it calls Set to emit a signal that the waiting thread can proceed. And frees all waiting threads. Once it is terminated, ManualResetEvent will remain signaled (that is, the thread of the call to WaitOne will immediately return without blocking) until it is manually reset. You can control the initial state of a ManualResetEvent by passing a Boolean value to the constructor, or false if the initial state is in the signaled state.
ManualResetEvent Example
Suppose you have a program that calls three asynchronous methods, and the code is as follows:
| The code is as follows |
Copy Code |
| public class Test { public void Todo (String message) { Console.WriteLine ("{0} {1}", DateTime.Now.ToString ("Yyyy-mm-dd HH:mm:ss"), message); } Private action<string> _todo = null; Public Test () { _todo = Todo; } Public IAsyncResult Begintodo (String message, AsyncCallback callback, object state) { Return _todo. BeginInvoke (message, callback, state); } public void Endtodo (IAsyncResult ar) { _todo. EndInvoke (AR); } } public class Program { static void Callback1 (IAsyncResult ar) { Test test = (test) ar. asyncstate; Test. Endtodo (AR); } static void Callback2 (IAsyncResult ar) { Test test = (test) ar. asyncstate; Test. Endtodo (AR); } static void Callback3 (IAsyncResult ar) { Test test = (test) ar. asyncstate; Test. Endtodo (AR); } static public void Main (string[] args) { Test test1 = new test (); Test1. Begintodo ("Test1", Callback1, test1); Test test2 = new test (); Test2. Begintodo ("Test2", Callback2, test2); Test test3 = new test (); Test3. Begintodo ("Test3", Callback3, test3); Console.readkey (); } } |
The results of the execution are shown in the following illustration:
That is, the order in which asynchronous methods are executed is not fixed, but sometimes we want them to execute sequentially, modifying the code as follows:
| The code is as follows |
Copy Code |
| public class Program { static void Callback1 (IAsyncResult ar) { Test test = (test) ar. asyncstate; Test. Endtodo (AR); Test test2 = new test (); Test2. Begintodo ("Test2", Callback2, test2); } static void Callback2 (IAsyncResult ar) { Test test = (test) ar. asyncstate; Test. Endtodo (AR); Test test3 = new test (); Test3. Begintodo ("Test3", Callback3, test3); } static void Callback3 (IAsyncResult ar) { Test test = (test) ar. asyncstate; Test. Endtodo (AR); } static public void Main (string[] args) { Test test1 = new test (); Test1. Begintodo ("Test1", Callback1, test1); Console.readkey (); } } |
Do you think it's a mess? Can you make the code as organized as it started, and execute it sequentially? The ManualResetEvent class appeared:
| The code is as follows |
Copy Code |
| public class Program { static ManualResetEvent done1 = new ManualResetEvent (false); static ManualResetEvent Done2 = new ManualResetEvent (false); static ManualResetEvent Done3 = new ManualResetEvent (false); static void Callback1 (IAsyncResult ar) { Test test = (test) ar. asyncstate; Test. Endtodo (AR); Done1. Set (); } static void Callback2 (IAsyncResult ar) { Test test = (test) ar. asyncstate; Test. Endtodo (AR); Done2. Set (); } static void Callback3 (IAsyncResult ar) { Test test = (test) ar. asyncstate; Test. Endtodo (AR); Done3. Set (); } static public void Main (string[] args) { Test test1 = new test (); Test1. Begintodo ("Test1", Callback1, test1); Done1. WaitOne (); Blocks the current thread and continues execution after set Test test2 = new test (); Test2. Begintodo ("Test2", Callback2, test2); Done2. WaitOne (); Blocks the current thread and continues execution after set Test test3 = new test (); Test3. Begintodo ("Test3", Callback3, test3); Done3. WaitOne (); Blocks the current thread and continues execution after set Console.readkey (); } } |