Directory (?) [-]
- Simple Introduction
- Use timeouts and cancellations
- Synchronization across a process or AppDomain
Simple Introduction
If you expect the operation to wait for a very short time, consider using a lightweight manual reset event, ManualResetEventSlim. It can emit signals and wait for events. From the name and use of the way, it is mainly to provide people-oriented operation, in the process based on the human understanding of the program is very familiar with the process of human control of the entire synchronization.
ManualResetEventSlim provides 3 common methods and 3 read-only properties.
constructor function:
- ManualResetEventSlim (): Initializes a new instance of the ManualResetEventSlim class with a non-signaled initial state.
- ManualResetEventSlim (Boolean): Class with a Boolean value that indicates whether the initial state is set to signaled.
A new instance of the ManualResetEventSlim class.
- ManualResetEventSlim (Boolean, Int32): Initializes a new instance of the ManualResetEventSlim class with a Boolean value that indicates whether the initial state is set to signaled and the specified spin count.
Method:
- Reset: Set event to False (cancel setting/Cancel signal)
- Set: Sets the event to true (set/signal), and if a task is waiting, it will get the signal and unblock it.
- Wait: Blocks the current task or thread until another thread sends a signal.
Property:
- IsSet: A bool value that indicates whether the event is set.
- Spincount: Number of spins to be performed before entering the kernel wait.
- WaitHandle: Provides access to the operating system object WaitHandle. This object allows you to wait for exclusive access to the shared resource.
Example of a program: In this example, ManualResetEventSlim is used, which makes task1,2,3 a sequential operation.
Using System;Using System.Text;Using System.Threading;Using System.threading.tasks;namespace sample5_7_manualreseteventslim{class Program {PrivateStaticint _tasknum =3;PrivateStatic task[] _tasks;PrivateStatic StringBuilder _strblder;PrivateConstint run_loop =10;PrivateStatic ManualResetEventSlim m_worker2event;PrivateStatic ManualResetEventSlim m_worker3event;PrivateStaticvoidWORK1 (int TaskID) {int i =0;String log ="";while (I < run_loop) {log = String.Format ("Time: {0} Task: #{1} Value: {2} =====\n", DateTime.Now.TimeOfDay, TaskID, i); i++;try {_strblder.append (log);}finally {M_worker2event.set ();}} }PrivateStaticvoidWORK2 (int TaskID) {int i =0;String log =""; M_worker2event.wait ();while ((I < Run_loop) && (m_worker2event.isset)) {log = String.Format ("Time: {0} Task: #{1} Value: {2} *****\n", DateTime.Now.TimeOfDay, TaskID, i); i++;try {_strblder.append (log);}finally {M_worker3event.set ();}} }PrivateStaticvoidWORK3 (int TaskID) {int i =0;String log =""; M_worker3event.wait ();while ((I < Run_loop) && (m_worker3event.isset)) {log = String.Format ("Time: {0} Task: #{1} Value: {2} ~~~~~\n", DateTime.Now.TimeOfDay, TaskID, i); i++;try {_strblder.append (log);}Finally {}}}Staticvoid Main (String[] args) {_tasks =New Task[_tasknum]; _strblder =New StringBuilder (); M_worker2event =New ManualResetEventSlim (False100); M_worker3event =New ManualResetEventSlim (False100); _tasks[0] = Task.Factory.StartNew (num) + = {var TaskID = (int) num; Work1 (TaskID); },0); _tasks[1] = Task.Factory.StartNew (num) + = {var TaskID = (int) num; WORK2 (TaskID); },1); _tasks[2] = Task.Factory.StartNew (num) + = {var TaskID = (int) num; Work3 (TaskID); }, 2); var finaltask = Task.Factory.ContinueWhenAll (_tasks, (Tasks) = {Task.waitall (_tasks); Console.WriteLine ( "=========================================================="); Console.WriteLine ( "All Phase is completed"); Console.WriteLine ( "=========================================================="); Console.WriteLine (_strblder); }); try {finaltask.wait ();} catch (AggregateException aex) {Console.WriteLine ( "Task Failed and Canceled "+ AEX. ToString ()); } finally {m_worker2event.dispose (); M_worker3event.dispose ();} Console.ReadLine (); } }}
Use timeouts and cancellations
The timeout mechanism is necessary for the synchronization of tasks, which also provides a way for users to set timeouts.
manualreseteventsilm.wait (int time_out);
Example of the program: In this example, Task 1 waits 5 seconds after setting the event, but the task 2,3 time-out is 2 seconds.
Using System;Using System.Text;Using System.Threading;Using System.threading.tasks;namespace sample5_7_manualreseteventslim{class Program {PrivateStaticint _tasknum =3;PrivateStatic task[] _tasks;PrivateStatic StringBuilder _strblder;PrivateConstint run_loop =10;PrivateStatic ManualResetEventSlim m_worker2event;PrivateStatic ManualResetEventSlim m_worker3event;PrivateStaticvoidWORK1 (int TaskID) {int i =0;String log ="";while (I < run_loop) {log = String.Format ("Time: {0} Task: #{1} Value: {2} =====\n", DateTime.Now.TimeOfDay, TaskID, i); i++;try {_strblder.append (log);}finally {System.Threading.Thread.Sleep (5000); M_worker2event.set (); } } }PrivateStaticvoidWORK2 (int TaskID) {int i =0;String log ="";if (!m_worker2event.wait () {Console.WriteLine ("Task 2 wait for event time out!!");Return }while ((I < Run_loop) && (m_worker2event.isset)) {log = String.Format ("Time: {0} Task: #{1} Value: {2} *****\n", DateTime.Now.TimeOfDay, TaskID, i); i++;try {_strblder.append (log);}finally {M_worker3event.set ();}} }PrivateStaticvoidWORK3 (int TaskID) {int i =0;String log ="";if (!m_worker3event.wait () {Console.WriteLine ("Task 3 wait for event time out!!");Return }while ((I < Run_loop) && (m_worker3event.isset)) {log = String.Format ("Time: {0} Task: #{1} Value: {2} ~~~~~\n", DateTime.Now.TimeOfDay, TaskID, i); i++;try {_strblder.append (log);}Finally {}}}Staticvoid Main (String[] args) {_tasks =New Task[_tasknum]; _strblder =New StringBuilder (); M_worker2event =New ManualResetEventSlim (False100); M_worker3event =New ManualResetEventSlim (False100); _tasks[0] = Task.Factory.StartNew (num) + = {var TaskID = (int) num; Work1 (TaskID); },0); _tasks[1] = Task.Factory.StartNew (num) + = {var TaskID = (int) num; WORK2 (TaskID); },1); _tasks[2] = Task.Factory.StartNew (num) + = {var TaskID = (int) num; Work3 (TaskID); }, 2); var finaltask = Task.Factory.ContinueWhenAll (_tasks, (Tasks) = {Task.waitall (_tasks); Console.WriteLine ( "=========================================================="); Console.WriteLine ( "All Phase is completed"); Console.WriteLine ( "=========================================================="); Console.WriteLine (_strblder); }); try {finaltask.wait ();} catch (AggregateException aex) {Console.WriteLine ( "Task Failed and Canceled "+ AEX. ToString ()); } finally {m_worker2event.dispose (); M_worker3event.dispose ();} Console.ReadLine (); } }}
It can be noted that task 1 is only blocking the Task2, but TASK3 is also affected by the timeout. The propagation of the time-out mechanism in the system will have a certain effect on the whole program.
Good aspect: Help all the modules of the system to understand that there are some anomalies in the system, to take action.
Bad aspect: some modules have no corresponding preparation for the timeout of other modules, which leads directly to a series of abnormal reactions, and the system crashes.
Synchronization across a process or AppDomain
If you need to implement a cross-process synchronization, you can use ManualResetEvent. There are certain differences between ManualResetEvent and ManualResetEventSlim, such as it has no isset attribute.
Method:
- Reset: Set event to False (cancel setting/Cancel signal)
- Set: Sets the event to true (set/signal), and if a task is waiting, it will get the signal and unblock it.
- WaitOne: Blocks the current task or thread until another thread sends a signal.
The use of ManualResetEvent and ManualResetEventSlim is basically consistent.
The use of lightweight manual reset events for C # parallel programming