Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of .NET synchronous and Asynchronous EventWaitHandle

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article is to share with you the content of the sample analysis of .NET synchronous and asynchronous EventWaitHandle. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

WaitHandle provides several methods for synchronization. A WaitOne () has been mentioned in the previous blog about Mutex, which is an example method. In addition, WaitHandle has three other static methods for synchronization:

SignalAndWait (WaitHandle, WaitHandle): signals the first WaitHandle and waits for the second in the form of atomic operations. That is, wake up the thread / process blocking on the first WaitHandle, and then wait for the second WaitHandle, and these two actions are atomic. Like WaitOne (), this method has two other overloaded methods, which use Int32 or TimeSpan to define the wait timeout and whether to exit from the synchronization domain of the context.

WaitAll (WaitHandle []): this is used to wait for all members of the WaitHandle array. If a job needs to be completed by everyone before it can be continued, then this method is a good choice. There are still two overloaded methods to control wait timeout, please refer to it yourself.

WaitAny (WaitHandle []): unlike WaitAll (), WaitAny returns as soon as a member of the array receives the signal. If you can start a job by waiting for the one to be finished as soon as possible, then WaitAny () is what you need. It also has two overloads that control wait timeouts.

Thread dependency

Mutex, like Monitor, is thread dependent. As we mentioned earlier, only threads that acquire object locks through Monitor.Enter () / TryEnter () can call Pulse () / Wait () / Exit (); similarly, only threads that gain ownership of Mutex 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 EventWaitHandle to wake up a thread blocking it.

Event Notification

EventWaitHandle, AutoResetEvent, and ManualResetEvent all have a "Event" in their names, but this has nothing to do with. Net's own event mechanism, which does not involve any delegates or event handlers. In contrast to the Monitor and Mutex that we encountered before, we can think of them as "events" that require threads to wait. Threads block themselves by waiting for the "occurrence" of these events. Once the event is complete, the blocked thread can continue to work after receiving the signal.

In conjunction with the three static methods SingnalAndWait () / WailAny () / WaitAll () on WaitHandle, EventWaitHandle provides its own unique methods to make "Event" complete and start over:

Bool:Set (): English version of MSDN:Sets the state of the event to signaled, allowing one or more waiting threads to proceed; Chinese version of MSDN: sets the event state to a terminated state, allowing one or more waiting threads to continue. At first glance, "signaled" and "termination" do not seem to correspond to each other, but when you think about it, the two statements are 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, the event is "terminated", so we send a signal to wake up the waiting thread, so the "signal has been sent" state is also reasonable. Two small details:

Both Chinese and English versions mention that this method allows "one" or "multiple" waiting threads to 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 Boolean return value: true; if the operation is successful; otherwise, false. However, MSDN does not tell us when the execution will fail, so you have to ask a Microsoft MVP.

Bool:Reset (): Sets the state of the event to nonsignaled, causing threads to block. Sets the event state to a non-terminating state, causing threads to block. Similarly, we need to understand that "nonsignaled" and "non-termination" are the same thing. Similarly, there is still a nonsense return value. The role of Reset () is equivalent to making the event "in progress" again, so that all threads of the event WaitOne () / WaitAll () / WaitAny () / SignalAndWait () will be blocked out again.

Constructor function

Take a look at the simplest of the many constructors of EventWaitHandle:

EventWaitHandle (Boolean initialState, EventResetMode mode): initializes a new instance of the EventWaitHandle class and specifies whether the wait handle is initially terminated and whether it resets automatically or manually. Most of the time we use false in the first parameter, so the new instance defaults to the "non-terminating" state. The second parameter, EventResetMode, is an enumeration with two values:

EventResetMode.AutoReset: when Set () is called and the current EventWaitHandle is transferred to the terminated state, if a thread is blocked on the current EventWaitHandle, then after releasing a thread, the EventWaitHandle will automatically reset (equivalent to automatically calling Reset ()) and return to the non-terminating state, and the remaining originally blocked threads (if any) will continue to block. If there is no thread blocking after calling Set (), EventWaitHandle will remain "terminated" until a thread tries to wait for the event, and that thread will not be blocked, after which EventWaitHandle will automatically reset and block all threads after that.

EventResetMode.ManualReset: when terminated, EventWaitHandle releases all waiting threads and remains terminated until it is manually reset, that is, until Reset () is called.

Well, 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 functionality. At this point, Set () can only wake up one of the many (if more than one) blocked threads. But there are still some differences between the two:

The function of Set () is not only to "wake up" but to "release", allowing the thread to continue to work (proceed); on the contrary, the thread awakened by Pulse () just reenters the Running state and participates in the contention for the object lock, and there is no guarantee that it will acquire the object lock.

The called state of Pulse () is not maintained. Therefore, if Pulse () is called when there is no waiting thread, the next thread that calls Monitor.Wait () will still be blocked, just as Pulse () has not been called. That is, Monitor.Pulse () works only at the time of the call, unlike Set (), which lasts until the next WaitXXX ().

When the Set () method of an EventWaitHandle working in ManualReset mode is called, it wakes up like Monitor.PulseAll (), and all blocked threads are awakened by a signal. And the difference between the two is exactly the same.

Take a look at the other constructors of EventWaitHandle:

EventWaitHandle (Boolean initialState, EventResetMode mode, String name): we have seen the first two parameters, and the third parameter, name, is used to specify the name of the synchronization event system-wide. Yes, as we mentioned in Mutex, because the parent class WaitHandle has the ability to span process domains, like Mutex, we can create a global EventWaitHandle for later use in interprocess notifications. Note that name is still case-sensitive and there are still problems with naming prefixes, which you can refer to here. When name is null or an empty string, this is equivalent to creating a local unnamed EventWaitHandle. Again, it is possible to return only an instance representing an EventWaitHandle with the same name because there is already an EventWaitHandle with the same name in the system. So in the end, again, if you need to know whether the EventWaitHandle was first created by you, 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,true was created successfully, and the false indicates that an event with the same name already exists.

EventWaitHandle (Boolean initialState, EventResetMode mode, String name, out Boolean createdNew, EventWaitHandleSecurity): for security, check out the example on this constructor directly. The security issues of global MutexEventWaitHandle should be paid more attention to than Mutex, because it is possible that hackers signal or organize your threads with the same event name, 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 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 item0; I

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report