Home Backend Development C#.Net Tutorial .NET Synchronization and Asynchronous EventWaitHandle

.NET Synchronization and Asynchronous EventWaitHandle

Apr 11, 2017 pm 02:05 PM


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
methods. :

##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
object

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
event handling

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:

  1. 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.

  2. 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.

  • ##bool:Reset(): Sets the state of the event to nonsignaled, causing threads to block. Sets the state of the event to nonsignaled, causing threads to block. Likewise, we need to understand that "nonsignaled" and "non-terminated" are the same thing. Also, there is still a nonsensical return value. The function of Reset() is equivalent to making the event "in progress" again, then all threads of the WaitOne()/WaitAll()/WaitAny()/SignalAndWait() event will be blocked again.

  • Constructor

    Let’s take a look at the most common constructor of EventWaitHandle Simple one:

    • 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:

    1. 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.

    2. ##EventResetMode.ManualReset

      : When terminated, EventWaitHandle releases all waiting threads and before manual reset, that is, Reset() It remains terminated until called.

    Okay, now we can clearly know when Set() is similar to Monitor.Pulse()/PulseAll() respectively:

      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.
    1. 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().
    When the Set() method of an EventWaitHandle working in ManualReset mode is called, its wake-up function is similar to Monitor.PulseAll(). All are Blocked threads will receive the signal and be awakened. The difference between the two is exactly the same as above.
  • Let’s take a look at other constructors of EventWaitHandle:
    • 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();
        }
    }
    Copy after login


    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!

    Statement of this Website
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

    Hot AI Tools

    Undresser.AI Undress

    Undresser.AI Undress

    AI-powered app for creating realistic nude photos

    AI Clothes Remover

    AI Clothes Remover

    Online AI tool for removing clothes from photos.

    Undress AI Tool

    Undress AI Tool

    Undress images for free

    Clothoff.io

    Clothoff.io

    AI clothes remover

    AI Hentai Generator

    AI Hentai Generator

    Generate AI Hentai for free.

    Hot Tools

    Notepad++7.3.1

    Notepad++7.3.1

    Easy-to-use and free code editor

    SublimeText3 Chinese version

    SublimeText3 Chinese version

    Chinese version, very easy to use

    Zend Studio 13.0.1

    Zend Studio 13.0.1

    Powerful PHP integrated development environment

    Dreamweaver CS6

    Dreamweaver CS6

    Visual web development tools

    SublimeText3 Mac version

    SublimeText3 Mac version

    God-level code editing software (SublimeText3)

    How to handle special characters in C language How to handle special characters in C language Apr 03, 2025 pm 03:18 PM

    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.

    What is the role of char in C strings What is the role of char in C strings Apr 03, 2025 pm 03:15 PM

    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 difference between char and wchar_t in C language The difference between char and wchar_t in C language Apr 03, 2025 pm 03:09 PM

    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.

    How to use various symbols in C language How to use various symbols in C language Apr 03, 2025 pm 04:48 PM

    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.

    The difference between multithreading and asynchronous c# The difference between multithreading and asynchronous c# Apr 03, 2025 pm 02:57 PM

    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.

    How to convert char in C language How to convert char in C language Apr 03, 2025 pm 03:21 PM

    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.

    What is the function of C language sum? What is the function of C language sum? Apr 03, 2025 pm 02:21 PM

    There is no built-in sum function in C language, so it needs to be written by yourself. Sum can be achieved by traversing the array and accumulating elements: Loop version: Sum is calculated using for loop and array length. Pointer version: Use pointers to point to array elements, and efficient summing is achieved through self-increment pointers. Dynamically allocate array version: Dynamically allocate arrays and manage memory yourself, ensuring that allocated memory is freed to prevent memory leaks.

    How to use char array in C language How to use char array in C language Apr 03, 2025 pm 03:24 PM

    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().

    See all articles