.NET Synchronization and Asynchronous EventWaitHandle
In the previous article we have mentioned Mutex and the protagonists of this article directly or indirectlyInherits from WaitHandle:
Mutex class, which we have already talked about in the previous article.
-
EventWaitHandle class and its derived classes AutoResetEvent and ManualResetEvent, this is the protagonist of this article. ##map
hore class, that is, semaphore, we will talk about it in the next article (suddenly I feel there is no need to introduce it) - WaitHandle provides several. Methods for synchronization. The previous blog about Mutex has already mentioned a WaitOne(), which is an instance method. In addition, WaitHandle has three other static
##SignalAndWait(WaitHandle, WaitHandle): In the form of atomic operation, send a signal to the first WaitHandle and wait for the second one, that is, wake up the thread blocked on the first WaitHandle. / process, and then wait for the second WaitHandle, and these two actions are atomic. Like WaitOne(), this method also has two overloaded methods, using Int32 or
respectively. Time- Span to define the wait timeout and whether to
- exit
from the synchronization domain of the contextWaitAll(WaitHandle[. ]): This is used to wait for all members in the WaitHandlearray. If a job needs to wait for everyone before it to complete, then this method is still a good choice. For overloaded methods that control waiting timeout, please refer to
WaitAny(WaitHandle[]): Unlike WaitAll(), WaitAny only waits until one member of the array receives a signal. Return. If you only need to wait for the fastest completion of a job, then WaitAny() is what you need. It also has two overloads for controlling wait timeout ##.
#Thread dependency- ##Mutex, like Monitor, has thread dependency. We have mentioned it before. Previously, only threads that obtained the
lock through Monitor.Enter()/TryEnter() can call Pulse()/Wait()/Exit(); similarly, only threads that obtain Mutex ownership can Execute the ReleaseMutex() method, otherwise an exception will be thrown. This is called thread dependency.
In contrast, EventWaitHandle and its derived classes AutoResetEvent and ManualResetEvent are thread-independent. Any thread can signal to EventWaitHandle to wake up the thread blocked on it.
The Semaphore to be mentioned in the next article is also thread-independent.
- Event notification
-
EventWaitHandle, AutoResetEvent, and ManualResetEvent all have an "Event" in their names, but this is not the same as. net's own
event mechanism has nothing to do with it, it does not involve any delegation or
procedures. Compared with the Monitor and Mutex we encountered before, which require threads to compete for "locks", we can understand them as some "events" that require threads to wait. The thread blocks itself by waiting for these events to "occur". Once the "event" is completed, the blocked thread can continue working after receiving the signal.
In order to cooperate with the three static methods SingnalAndWait()/WailAny()/WaitAll() on WaitHandle, EventWaitHandle provides its own unique method to complete and restart "Event":
bool:Set(): English version MSDN: Sets the state of the event to signaled, allowing one or more waiting threads to proceed; Chinese version MSDN: Sets the event stateSet to terminated state, allowing one or more waiting threads to continue. At first glance, "signaled" and "termination" don't seem to correspond, but when you think about it carefully, the two terms are actually not contradictory. If the event is in progress, of course there is no "termination", then other
threads need to wait; once the event is completed, then the event is "termination", so we send a signal to wake up the waiting thread, so the "signal Sent" status is also reasonable. Two small details:No matter the Chinese or English version, it is mentioned that this method can make "one" or "multiple" waiting threads "continue/Proceed" (note that it is not "wake up"). So this method is similar to Monitor.Pulse() and Monitor.PulseAll() in the "wake up" action. As for when it is similar to Pulse() and when it is similar to PulseAll(), read on.
This method has a bool return value: true if the operation is successful; otherwise, false. However, MSDN does not tell us when the execution will fail. You can only ask a Microsoft MVP.
- EventWaitHandle(Boolean initialState, EventResetMode mode): Initializes a new instance of the EventWaitHandle class and specifies whether the wait handle is initially in a terminated state, and whether it is reset automatically or manually Reset. Most of the time we will use false in the first parameter so that the new instance will default to the "non-terminated" state. The second parameter EventResetMode is an enumeration with a total of two values:
EventResetMode.AutoReset: When Set() is called, the current EventWaitHandle is transferred to In the terminated state, if a thread is blocked on the current EventWaitHandle, the EventWaitHandle will automatically reset (equivalent to automatically calling Reset()) after releasing a thread and transfer to the non-terminated state again, and the remaining original Blocked threads (if any) will continue to block. If no thread is blocked after calling Set(), then the EventWaitHandle will remain in the "terminated" state until a thread tries to wait for the event. This thread will not be blocked. After that, the EventWaitHandle will automatically reset and block all threads after that.
- ##EventResetMode.ManualReset
: When terminated, EventWaitHandle releases all waiting threads and before manual reset, that is, Reset() It remains terminated until called.
- When EventWaitHandle works in AutoReset mode, Set() is similar to Monitor.Pulse() in terms of wake-up function. At this time, Set() can only wake up one of many (if there are multiple) blocked threads. But there are still some differences between the two:
- The function of Set() is not just to "wake up" but to "release", allowing the thread to continue working (proceed); on the contrary, The thread awakened by Pulse() only re-enters the Running state and participates in the competition for the object lock. No one can guarantee that it will obtain the object lock.
- The called state of Pulse() will not be maintained. Therefore, if Pulse() is called when there are no waiting threads, the next thread that calls Monitor.Wait() will still be blocked, as if Pulse() had never been called. In other words, Monitor.Pulse() only takes effect when it is called, unlike Set(), which will continue to the next WaitXXX().
EventWaitHandle(Boolean initialState, EventResetMode mode, String name): We have already seen the first two parameters, and the third parameter name is used to specify synchronization events within the system. The name. Yes, as we mentioned in the Mutex article, since the parent class WaitHandle has the ability to cross process domains, like Mutex, we can create a global EventWaitHandle and later use it for inter-process notifications . Note that name is still case-sensitive, and there are still naming prefix issues, you can refer to here. When name is null or an empty string, this is equivalent to creating a local, unnamed EventWaitHandle. Still the same, it is possible that only one instance is returned to represent the EventWaitHandle with the same name because there is already an EventWaitHandle with the same name in the system. So in the end it's still the same, if you need to know whether this EventWaitHandle was created by you first, you need to use one of the following two constructors.
EventWaitHandle(Boolean initialState, EventResetMode mode, String name, out Boolean createdNew): createdNew is used to indicate whether the EventWaitHandle was successfully created, true indicates success, false Indicates that an event with the same name already exists.
EventWaitHandle(Boolean initialState, EventResetMode mode, String name, out Boolean createdNew, EventWaitHandleSecurity): Regarding security issues, just check the example on this constructor . The security issues of global MutexEventWaitHandle should be paid more attention to than that of Mutex, because it is possible for hackers to use the same event name to send signals or organize your threads, which may seriously harm your business logic.
MSDN Demo
##
using System;using System.Threading;public class Example { // The EventWaitHandle used to demonstrate the difference // between AutoReset and ManualReset synchronization events. // private static EventWaitHandle ewh; // A counter to make sure all threads are started and // blocked before any are released. A Long is used to show // the use of the 64-bit Interlocked methods. // private static long threadCount = 0; // An AutoReset event that allows the main thread to block // until an exiting thread has decremented the count. // private static EventWaitHandle clearCount = new EventWaitHandle(false, EventResetMode.AutoReset); [MTAThread] public static void Main() { // Create an AutoReset EventWaitHandle. // ewh = new EventWaitHandle(false, EventResetMode.AutoReset); // Create and start five numbered threads. Use the // ParameterizedThreadStart delegate, so the thread // number can be passed as an argument to the Start // method. for (int i = 0; i <= 4; i++) { Thread t = new Thread( new ParameterizedThreadStart(ThreadProc) ); t.Start(i); } // Wait until all the threads have started and blocked. // When multiple threads use a 64-bit value on a 32-bit // system, you must access the value through the // Interlocked class to guarantee thread safety. // while (Interlocked.Read(ref threadCount) < 5) { Thread.Sleep(500); } // Release one thread each time the user presses ENTER, // until all threads have been released. // while (Interlocked.Read(ref threadCount) > 0) { Console.WriteLine("Press ENTER to release a waiting thread."); Console.ReadLine(); // SignalAndWait signals the EventWaitHandle, which // releases exactly one thread before resetting, // because it was created with AutoReset mode. // SignalAndWait then blocks on clearCount, to // allow the signaled thread to decrement the count // before looping again. // WaitHandle.SignalAndWait(ewh, clearCount); } Console.WriteLine(); // Create a ManualReset EventWaitHandle. // ewh = new EventWaitHandle(false, EventResetMode.ManualReset); // Create and start five more numbered threads. // for(int i=0; i<=4; i++) { Thread t = new Thread( new ParameterizedThreadStart(ThreadProc) ); t.Start(i); } // Wait until all the threads have started and blocked. // while (Interlocked.Read(ref threadCount) < 5) { Thread.Sleep(500); } // Because the EventWaitHandle was created with // ManualReset mode, signaling it releases all the // waiting threads. // Console.WriteLine("Press ENTER to release the waiting threads."); Console.ReadLine(); ewh.Set(); } public static void ThreadProc(object data) { int index = (int) data; Console.WriteLine("Thread {0} blocks.", data); // Increment the count of blocked threads. Interlocked.Increment(ref threadCount); // Wait on the EventWaitHandle. ewh.WaitOne(); Console.WriteLine("Thread {0} exits.", data); // Decrement the count of blocked threads. Interlocked.Decrement(ref threadCount); // After signaling ewh, the main thread blocks on // clearCount until the signaled thread has // decremented the count. Signal it now. // clearCount.Set(); } }
The above is the detailed content of .NET Synchronization and Asynchronous EventWaitHandle. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

In C, the char type is used in strings: 1. Store a single character; 2. Use an array to represent a string and end with a null terminator; 3. Operate through a string operation function; 4. Read or output a string from the keyboard.

The usage methods of symbols in C language cover arithmetic, assignment, conditions, logic, bit operators, etc. Arithmetic operators are used for basic mathematical operations, assignment operators are used for assignment and addition, subtraction, multiplication and division assignment, condition operators are used for different operations according to conditions, logical operators are used for logical operations, bit operators are used for bit-level operations, and special constants are used to represent null pointers, end-of-file markers, and non-numeric values.

In C language, special characters are processed through escape sequences, such as: \n represents line breaks. \t means tab character. Use escape sequences or character constants to represent special characters, such as char c = '\n'. Note that the backslash needs to be escaped twice. Different platforms and compilers may have different escape sequences, please consult the documentation.

The difference between multithreading and asynchronous is that multithreading executes multiple threads at the same time, while asynchronously performs operations without blocking the current thread. Multithreading is used for compute-intensive tasks, while asynchronously is used for user interaction. The advantage of multi-threading is to improve computing performance, while the advantage of asynchronous is to not block UI threads. Choosing multithreading or asynchronous depends on the nature of the task: Computation-intensive tasks use multithreading, tasks that interact with external resources and need to keep UI responsiveness use asynchronous.

In C language, the main difference between char and wchar_t is character encoding: char uses ASCII or extends ASCII, wchar_t uses Unicode; char takes up 1-2 bytes, wchar_t takes up 2-4 bytes; char is suitable for English text, wchar_t is suitable for multilingual text; char is widely supported, wchar_t depends on whether the compiler and operating system support Unicode; char is limited in character range, wchar_t has a larger character range, and special functions are used for arithmetic operations.

In C language, char type conversion can be directly converted to another type by: casting: using casting characters. Automatic type conversion: When one type of data can accommodate another type of value, the compiler automatically converts it.

The char array stores character sequences in C language and is declared as char array_name[size]. The access element is passed through the subscript operator, and the element ends with the null terminator '\0', which represents the end point of the string. The C language provides a variety of string manipulation functions, such as strlen(), strcpy(), strcat() and strcmp().

char and unsigned char are two data types that store character data. The main difference is the way to deal with negative and positive numbers: value range: char signed (-128 to 127), and unsigned char unsigned (0 to 255). Negative number processing: char can store negative numbers, unsigned char cannot. Bit mode: char The highest bit represents the symbol, unsigned char Unsigned bit. Arithmetic operations: char and unsigned char are signed and unsigned types, and their arithmetic operations are different. Compatibility: char and unsigned char
