Can anyone give me a headstart on the topic of threading? I think I know how to do a few things but I need to know how to do the following:
Setup a main thread that will stay active until I signal it to stop(in case you wonder, it will terminate when data is received). Then i want a second thread to start which will capture data from a textbox and should quit when I signal it to that of which occurs when the user presses the enter key.
Cheers!
This is how I do it...
public class ThreadA {
public ThreadA(object[] args) {
...
}
public void Run() {
while (true) {
Thread.sleep(1000); // wait 1 second for something to happen.
doStuff();
if(conditionToExitReceived) // what im waiting for...
break;
}
//perform cleanup if there is any...
}
}
Then to run this in its own thread... ( I do it this way because I also want to send args to the thread)
private void FireThread(){
Thread thread = new Thread(new ThreadStart(this.startThread));
thread.start();
}
private void (startThread){
new ThreadA(args).Run();
}
The thread is created by calling "FireThread()"
The newly created thread will run until its condition to stop is met, then it dies...
You can signal the "main" with delegates, to tell it when the thread has died.. so you can then start the second one...
Best to read through : This MSDN Article
Thread th = new Thread(function1);
th.Start();
th.Abort();
void function1(){
//code here
}
Use a static AutoResetEvent in your spawned threads to call back to the main thread using the Set() method. This guy has a fairly good demo in SO on how to use it.
AutoResetEvent clarification
From UI (thread1) I want to create a progress UI(thread2).
Progress UI creates a task in thread3 and waits for its completion.
The task(thread3) completes and invoke closing of progress UI which must be executed in thread2.
For closing operation I use AsyncOperationManager to capture context of thread2 and then execute POST method from thread4.
But closing always happens from some another thread.
All the code below is from ProgressWindows class.
_currentTask = new Progress<double>(Close); // I call this in progress UI constructor.
// This is invoked in constructor of Progress class which is used inside ProgressWindow.
_asyncOperation = AsyncOperationManager.CreateOperation(null);
public static void Run2(Action action)
{
Debug.WriteLine(":: Run2 in thread: {0}", Thread.CurrentThread.ManagedThreadId);
var th = new Thread(_ =>
{
Debug.WriteLine(":: StartNew in thread: {0}", Thread.CurrentThread.ManagedThreadId);
var progress = new ProgressWindow();
progress.Run(action);
});
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
public void Run(Action action)
{
Debug.WriteLine(":: Run in thread: {0}", Thread.CurrentThread.ManagedThreadId);
SetupProgressBar();
RunTask(action);
ShowDialog();
}
private void RunTask(Action action)
{
Task.Factory.StartNew(action).ContinueWith(_ => _currentTask.OnCompleted(null));
}
private void Close(object state)
{
Debug.WriteLine(":: Close in thread: {0}", Thread.CurrentThread.ManagedThreadId);
Hide();
Close();
}
The question is:
private void RunTask(Action action)
{
Task.Factory.StartNew(action).ContinueWith(_ => _currentTask.OnCompleted(null));
}
You see, _currentTask.OnCompleted(null) is invoked from another thread, but _currentTaskof type Progress uses context captured in the UI thread, but OnCompletedis always invoked from another thread other than UI thread. Why? It must be in the same context.
Update 1:
Mixing System.Threading.SynchronizationContext with System.Windows.Form.WindowsFormsSynchronizationContext and System.Windows.Threading.DispatcherSynchronizationContext
Synchronization context in asynchronous WCF per call service
Force WCF to use one thread
AsyncOperationManager works differently depending on context where AsyncOperationManager.CreateOperation was invoked.
Denending on context, AsyncOperationManager.CreateOperation may create three contexts:
System.Threading.SynchronizationContext
System.Windows.Form.WindowsFormsSynchronizationContext System.Windows.Threading.DispatcherSynchronizationContext
In my case when I capture context before ShowDialog, I capture thread sync context,
but if I invoke AsyncOperationManager.CreateOperation within OnLoad event, I capture
System.Windows.Form.WindowsFormsSynchronizationContext or DispatcherSynchronizationContext
depending on WindowsForms or WPF is used. That was the source of error.
I would cut it down to just using Dispatcher.BeginInvoke.
But to leave all the code with Progress, I just placed AsyncOperationManager.CreateOperation and creating new background thread inside OnLoad of ProgressWindow UI. It has resolved the issue.
I have the following C# code:
using System;
using System.Threading;
// Simple threading scenario: Start a static method running
// on a second thread.
public class ThreadExample {
// The ThreadProc method is called when the thread starts.
// It loops ten times, writing to the console and yielding
// the rest of its time slice each time, and then ends.
public static void ThreadProc() {
for (int i = 0; i < 10; i++) {
Console.WriteLine("ThreadProc: {0}", i);
// Yield the rest of the time slice.
Thread.Sleep(0);
}
}
public static void Main() {
Console.WriteLine("Main thread: Start a second thread.");
// The constructor for the Thread class requires a ThreadStart
// delegate that represents the method to be executed on the
// thread. C# simplifies the creation of this delegate.
Thread t = new Thread(new ThreadStart(ThreadProc));
// Start ThreadProc. Note that on a uniprocessor, the new
// thread does not get any processor time until the main thread
// is preempted or yields. Uncomment the Thread.Sleep that
// follows t.Start() to see the difference.
t.Start();
//Thread.Sleep(0);
for (int i = 0; i < 4; i++) {
Console.WriteLine("Main thread: Do some work.");
Thread.Sleep(0);
}
Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.");
t.Join();
Console.WriteLine("Main thread: ThreadProc.Join has returned. Press Enter to end program.");
Console.ReadLine();
}
}
It's a long time since I studied the thread to university, the only thing that I still remember is:
thread execution is pretty unpredictable and may vary based underlayng
OS.
So the real question is: why I can't be sure not even about the first execution of ThreadProc? What happen when I execute t.Start()? Why ThreadProc: 0 isn't printed immediately after Main thread: Start a second thread in every execution?
Why I can't be sure not even about the first execution of ThreadProc?
Because this is nondeterministic neither by .NET nor Windows OS documentation (I suppose you are using Windows)
What happen when I execute t.Start()?
Thread will be scheduled by OS for execution. MSDN: "Causes a thread to be scheduled for execution."
Why ThreadProc: 0 isn't printed immediately after Main thread: Start a
second thread in every execution?
Because there is some delay between Thread.Start() call and actual thread start
Possible duplicate: What is the difference ManualResetEvent and AutoResetEvent in .net?
What is the difference between ManualResetEvent and AutoResetEvent ? (Example could be helpful).
ManualResetEvent is like a gate in a field - once it's been opened, it lets people through until someone shuts it.
AutoResetEvent is like a turnstile in a train station - once you've put the ticket in, one person can go through, but only one.
Here's an example - 5 threads are all waiting for the same event, which is set once per second. With a manual reset event, all the threads "go through the gate" as soon as it's been set once. With an auto-reset event, only one goes at a time.
using System;
using System.Threading;
class Test
{
static void Main()
{
// Change to AutoResetEvent to see different behaviour
EventWaitHandle waitHandle = new ManualResetEvent(false);
for (int i = 0; i < 5; i++)
{
int threadNumber = i;
new Thread(() => WaitFor(threadNumber, waitHandle)).Start();
}
// Wait for all the threads to have started
Thread.Sleep(500);
// Now release the handle three times, waiting a
// second between each time
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Main thread setting");
waitHandle.Set();
Thread.Sleep(1000);
}
}
static void WaitFor(int threadNumber, EventWaitHandle waitHandle)
{
Console.WriteLine("Thread {0} waiting", threadNumber);
waitHandle.WaitOne();
Console.WriteLine("Thread {0} finished", threadNumber);
}
}
Sample output for ManualResetEvent:
Thread 0 waiting
Thread 4 waiting
Thread 1 waiting
Thread 2 waiting
Thread 3 waiting
Main thread setting
Thread 2 finished
Thread 1 finished
Thread 0 finished
Thread 4 finished
Thread 3 finished
Main thread setting
Main thread setting
Sample output for AutoResetEvent:
Thread 0 waiting
Thread 1 waiting
Thread 2 waiting
Thread 3 waiting
Thread 4 waiting
Main thread setting
Thread 3 finished
Main thread setting
Thread 2 finished
Main thread setting
Thread 1 finished
(The program then just hangs, as there are two threads still waiting for the event to be set, and nothing is going to set it.)
I have read the documentation on this and I think I understand. An AutoResetEvent resets when the code passes through event.WaitOne(), but a ManualResetEvent does not.
Is this correct?
Yes. It's like the difference between a tollbooth and a door. The ManualResetEvent is the door, which needs to be closed (reset) manually. The AutoResetEvent is a tollbooth, allowing one car to go by and automatically closing before the next one can get through.
Just imagine that the AutoResetEvent executes WaitOne() and Reset() as a single atomic operation.
The AutoResetEvent also guarantees to only release one waiting thread.
The short answer is yes. The most important difference is that an AutoResetEvent will only allow one single waiting thread to continue. A ManualResetEvent on the other hand will keep allowing threads, several at the same time even, to continue until you tell it to stop (Reset it).
Taken from C# 3.0 Nutshell book, by
Joseph Albahari
Threading in C# - Free E-Book
A ManualResetEvent is a variation on AutoResetEvent. It differs in that it doesn't automatically reset after a thread is let through on a WaitOne call, and so functions like a gate: calling Set opens the gate, allowing any number of threads that WaitOne at the gate through; calling Reset closes the gate, causing, potentially, a queue of waiters to accumulate until its next opened.
One could simulate this functionality with a boolean "gateOpen" field (declared with the volatile keyword) in combination with "spin-sleeping" – repeatedly checking the flag, and then sleeping for a short period of time.
ManualResetEvents are sometimes used to signal that a particular operation is complete, or that a thread's completed initialization and is ready to perform work.
I created simple examples to clarify understanding of ManualResetEvent vs AutoResetEvent.
AutoResetEvent: lets assume you have 3 workers thread. If any of those threads will call WaitOne() all other 2 threads will stop execution and wait for signal. I am assuming they are using WaitOne(). It is like; if I do not work, nobody works. In first example you can see that
autoReset.Set();
Thread.Sleep(1000);
autoReset.Set();
When you call Set() all threads will work and wait for signal. After 1 second I am sending second signal and they execute and wait (WaitOne()). Think about these guys are soccer team players and if one player says I will wait until manager calls me, and others will wait until manager tells them to continue (Set())
public class AutoResetEventSample
{
private AutoResetEvent autoReset = new AutoResetEvent(false);
public void RunAll()
{
new Thread(Worker1).Start();
new Thread(Worker2).Start();
new Thread(Worker3).Start();
autoReset.Set();
Thread.Sleep(1000);
autoReset.Set();
Console.WriteLine("Main thread reached to end.");
}
public void Worker1()
{
Console.WriteLine("Entered in worker 1");
for (int i = 0; i < 5; i++) {
Console.WriteLine("Worker1 is running {0}", i);
Thread.Sleep(2000);
autoReset.WaitOne();
}
}
public void Worker2()
{
Console.WriteLine("Entered in worker 2");
for (int i = 0; i < 5; i++) {
Console.WriteLine("Worker2 is running {0}", i);
Thread.Sleep(2000);
autoReset.WaitOne();
}
}
public void Worker3()
{
Console.WriteLine("Entered in worker 3");
for (int i = 0; i < 5; i++) {
Console.WriteLine("Worker3 is running {0}", i);
Thread.Sleep(2000);
autoReset.WaitOne();
}
}
}
In this example you can clearly see that when you first hit Set() it will let all threads go, then after 1 second it signals all threads to wait! As soon as you set them again regardless they are calling WaitOne() inside, they will keep running because you have to manually call Reset() to stop them all.
manualReset.Set();
Thread.Sleep(1000);
manualReset.Reset();
Console.WriteLine("Press to release all threads.");
Console.ReadLine();
manualReset.Set();
It is more about Referee/Players relationship there regardless of any of the player is injured and wait for playing others will continue to work. If Referee says wait (Reset()) then all players will wait until next signal.
public class ManualResetEventSample
{
private ManualResetEvent manualReset = new ManualResetEvent(false);
public void RunAll()
{
new Thread(Worker1).Start();
new Thread(Worker2).Start();
new Thread(Worker3).Start();
manualReset.Set();
Thread.Sleep(1000);
manualReset.Reset();
Console.WriteLine("Press to release all threads.");
Console.ReadLine();
manualReset.Set();
Console.WriteLine("Main thread reached to end.");
}
public void Worker1()
{
Console.WriteLine("Entered in worker 1");
for (int i = 0; i < 5; i++) {
Console.WriteLine("Worker1 is running {0}", i);
Thread.Sleep(2000);
manualReset.WaitOne();
}
}
public void Worker2()
{
Console.WriteLine("Entered in worker 2");
for (int i = 0; i < 5; i++) {
Console.WriteLine("Worker2 is running {0}", i);
Thread.Sleep(2000);
manualReset.WaitOne();
}
}
public void Worker3()
{
Console.WriteLine("Entered in worker 3");
for (int i = 0; i < 5; i++) {
Console.WriteLine("Worker3 is running {0}", i);
Thread.Sleep(2000);
manualReset.WaitOne();
}
}
}
autoResetEvent.WaitOne()
is similar to
try
{
manualResetEvent.WaitOne();
}
finally
{
manualResetEvent.Reset();
}
as an atomic operation
OK, normally it does not a good practice to add 2 answers in same thread, but I did not want to edit/delete my previous answer, since it can help on another manner.
Now, I created, much more comprehensive, and easy to understand, run-to-learn console app snippet below.
Just run the examples on two different consoles, and observe behaviour. You will get much more clear idea there what is happening behind the scenes.
Manual Reset Event
using System;
using System.Threading;
namespace ConsoleApplicationDotNetBasics.ThreadingExamples
{
public class ManualResetEventSample
{
private readonly ManualResetEvent _manualReset = new ManualResetEvent(false);
public void RunAll()
{
new Thread(Worker1).Start();
new Thread(Worker2).Start();
new Thread(Worker3).Start();
Console.WriteLine("All Threads Scheduled to RUN!. ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Main Thread is waiting for 15 seconds, observe 3 thread behaviour. All threads run once and stopped. Why? Because they call WaitOne() internally. They will wait until signals arrive, down below.");
Thread.Sleep(15000);
Console.WriteLine("1- Main will call ManualResetEvent.Set() in 5 seconds, watch out!");
Thread.Sleep(5000);
_manualReset.Set();
Thread.Sleep(2000);
Console.WriteLine("2- Main will call ManualResetEvent.Set() in 5 seconds, watch out!");
Thread.Sleep(5000);
_manualReset.Set();
Thread.Sleep(2000);
Console.WriteLine("3- Main will call ManualResetEvent.Set() in 5 seconds, watch out!");
Thread.Sleep(5000);
_manualReset.Set();
Thread.Sleep(2000);
Console.WriteLine("4- Main will call ManualResetEvent.Reset() in 5 seconds, watch out!");
Thread.Sleep(5000);
_manualReset.Reset();
Thread.Sleep(2000);
Console.WriteLine("It ran one more time. Why? Even Reset Sets the state of the event to nonsignaled (false), causing threads to block, this will initial the state, and threads will run again until they WaitOne().");
Thread.Sleep(10000);
Console.WriteLine();
Console.WriteLine("This will go so on. Everytime you call Set(), ManualResetEvent will let ALL threads to run. So if you want synchronization between them, consider using AutoReset event, or simply user TPL (Task Parallel Library).");
Thread.Sleep(5000);
Console.WriteLine("Main thread reached to end! ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);
}
public void Worker1()
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine("Worker1 is running {0}/10. ThreadId: {1}.", i, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(5000);
// this gets blocked until _autoReset gets signal
_manualReset.WaitOne();
}
Console.WriteLine("Worker1 is DONE. ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);
}
public void Worker2()
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine("Worker2 is running {0}/10. ThreadId: {1}.", i, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(5000);
// this gets blocked until _autoReset gets signal
_manualReset.WaitOne();
}
Console.WriteLine("Worker2 is DONE. ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);
}
public void Worker3()
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine("Worker3 is running {0}/10. ThreadId: {1}.", i, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(5000);
// this gets blocked until _autoReset gets signal
_manualReset.WaitOne();
}
Console.WriteLine("Worker3 is DONE. ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);
}
}
}
Auto Reset Event
using System;
using System.Threading;
namespace ConsoleApplicationDotNetBasics.ThreadingExamples
{
public class AutoResetEventSample
{
private readonly AutoResetEvent _autoReset = new AutoResetEvent(false);
public void RunAll()
{
new Thread(Worker1).Start();
new Thread(Worker2).Start();
new Thread(Worker3).Start();
Console.WriteLine("All Threads Scheduled to RUN!. ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Main Thread is waiting for 15 seconds, observe 3 thread behaviour. All threads run once and stopped. Why? Because they call WaitOne() internally. They will wait until signals arrive, down below.");
Thread.Sleep(15000);
Console.WriteLine("1- Main will call AutoResetEvent.Set() in 5 seconds, watch out!");
Thread.Sleep(5000);
_autoReset.Set();
Thread.Sleep(2000);
Console.WriteLine("2- Main will call AutoResetEvent.Set() in 5 seconds, watch out!");
Thread.Sleep(5000);
_autoReset.Set();
Thread.Sleep(2000);
Console.WriteLine("3- Main will call AutoResetEvent.Set() in 5 seconds, watch out!");
Thread.Sleep(5000);
_autoReset.Set();
Thread.Sleep(2000);
Console.WriteLine("4- Main will call AutoResetEvent.Reset() in 5 seconds, watch out!");
Thread.Sleep(5000);
_autoReset.Reset();
Thread.Sleep(2000);
Console.WriteLine("Nothing happened. Why? Becasuse Reset Sets the state of the event to nonsignaled, causing threads to block. Since they are already blocked, it will not affect anything.");
Thread.Sleep(10000);
Console.WriteLine("This will go so on. Everytime you call Set(), AutoResetEvent will let another thread to run. It will make it automatically, so you do not need to worry about thread running order, unless you want it manually!");
Thread.Sleep(5000);
Console.WriteLine("Main thread reached to end! ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);
}
public void Worker1()
{
for (int i = 1; i <= 5; i++)
{
Console.WriteLine("Worker1 is running {0}/5. ThreadId: {1}.", i, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(500);
// this gets blocked until _autoReset gets signal
_autoReset.WaitOne();
}
Console.WriteLine("Worker1 is DONE. ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);
}
public void Worker2()
{
for (int i = 1; i <= 5; i++)
{
Console.WriteLine("Worker2 is running {0}/5. ThreadId: {1}.", i, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(500);
// this gets blocked until _autoReset gets signal
_autoReset.WaitOne();
}
Console.WriteLine("Worker2 is DONE. ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);
}
public void Worker3()
{
for (int i = 1; i <= 5; i++)
{
Console.WriteLine("Worker3 is running {0}/5. ThreadId: {1}.", i, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(500);
// this gets blocked until _autoReset gets signal
_autoReset.WaitOne();
}
Console.WriteLine("Worker3 is DONE. ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);
}
}
}
AutoResetEvent maintains a boolean variable in memory. If the boolean variable is false then it blocks the thread and if the boolean variable is true it unblocks the thread.
When we instantiate an AutoResetEvent object, we pass the default value of boolean value in the constructor. Below is the syntax of instantiate an AutoResetEvent object.
AutoResetEvent autoResetEvent = new AutoResetEvent(false);
WaitOne method
This method blocks the current thread and wait for the signal by other thread. WaitOne method puts the current thread into a Sleep thread state. WaitOne method returns true if it receives the signal else returns false.
autoResetEvent.WaitOne();
Second overload of WaitOne method wait for the specified number of seconds. If it does not get any signal thread continues its work.
static void ThreadMethod()
{
while(!autoResetEvent.WaitOne(TimeSpan.FromSeconds(2)))
{
Console.WriteLine("Continue");
Thread.Sleep(TimeSpan.FromSeconds(1));
}
Console.WriteLine("Thread got signal");
}
We called WaitOne method by passing the 2 seconds as arguments. In the while loop, it wait for the signal for 2 seconds then it continues its work. When the thread got the signal WaitOne returns true and exits the loop and print the "Thread got signal".
Set method
AutoResetEvent Set method sent the signal to the waiting thread to proceed its work. Below is the syntax of calling Set method.
autoResetEvent.Set();
ManualResetEvent maintains a boolean variable in memory. When the boolean variable is false then it blocks all threads and when the boolean variable is true it unblocks all threads.
When we instantiate a ManualResetEvent, we initialize it with default boolean value.
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
In the above code, we initialize the ManualResetEvent with false value, that means all the threads which calls the WaitOne method will block until some thread calls the Set() method.
If we initialize ManualResetEvent with true value, all the threads which calls the WaitOne method will not block and free to proceed further.
WaitOne Method
This method blocks the current thread and wait for the signal by other thread. It returns true if its receives a signal else returns false.
Below is the syntax of calling WaitOne method.
manualResetEvent.WaitOne();
In the second overload of WaitOne method, we can specify the time interval till the current thread wait for the signal. If within time internal, it does not receives a signal it returns false and goes into the next line of method.
Below is the syntax of calling WaitOne method with time interval.
bool isSignalled = manualResetEvent.WaitOne(TimeSpan.FromSeconds(5));
We have specify 5 seconds into the WaitOne method. If the manualResetEvent object does not receives a signal between 5 seconds, it set the isSignalled variable to false.
Set Method
This method is used for sending the signal to all waiting threads. Set() Method set the ManualResetEvent object boolean variable to true. All the waiting threads are unblocked and proceed further.
Below is the syntax of calling Set() method.
manualResetEvent.Set();
Reset Method
Once we call the Set() method on the ManualResetEvent object, its boolean remains true. To reset the value we can use Reset() method. Reset method change the boolean value to false.
Below is the syntax of calling Reset method.
manualResetEvent.Reset();
We must immediately call Reset method after calling Set method if we want to send signal to threads multiple times.
Yes. This is absolutely correct.
You could see ManualResetEvent as a way to indicate state. Something is on (Set) or off (Reset). An occurrence with some duration. Any thread waiting for that state to happen can proceed.
An AutoResetEvent is more comparable to a signal. A one shot indication that something has happened. An occurrence without any duration. Typically but not necessarily the "something" that has happened is small and needs to be handled by a single thread - hence the automatic reset after a single thread have consumed the event.
Yes, thats right.
You can get an idea by the usage of these two.
If you need to tell that you are finished with some work and other (threads) waiting for this can now proceed, you should use ManualResetEvent.
If you need to have mutual exclusive access to any resource, you should use AutoResetEvent.
If you want to understand AutoResetEvent and ManualResetEvent you need to understand not threading but interrupts!
.NET wants to conjure up low-level programming the most distant possible.
An interrupts is something used in low-level programming which equals to a signal that from low became high (or viceversa). When this happens the program interrupt its normal execution and move the execution pointer to the function that handles this event.
The first thing to do when an interrupt happend is to reset its state, becosa the hardware works in this way:
a pin is connected to a signal and the hardware listen for it to change (the signal could have only two states).
if the signal changes means that something happened and the hardware put a memory variable to the state happened (and it remain like this even if the signal change again).
the program notice that variable change states and move the execution to a handling function.
here the first thing to do, to be able to listen again this interrupt, is to reset this memory variable to the state not-happened.
This is the difference between ManualResetEvent and AutoResetEvent.
If a ManualResetEvent happen and I do not reset it, the next time it happens I will not be able to listen it.