C# Thread won't sleep? - c#

I have this code :
void Main()
{
System.Timers.Timer t = new System.Timers.Timer (1000);
t.Enabled=true;
t.Elapsed+= (sender, args) =>c();
Console.ReadLine();
}
int h=0;
public void c()
{
h++;
new Thread(() => doWork(h)).Start();
}
public void doWork(int h)
{
Thread.Sleep(3000);
h.Dump();
}
I wanted to see what happens if the interval is 1000 ms and the job process is 3000 ms.
However I saw a strange behavior -
the 3000 ms delay occurs only at the start !
How can I make each doWork sleep 3000 ms?
As you can see here, at the beginning there is a 3 second delay, and then it iterates 1 second each.

Every time the timer ticks, you start a thread to do some sleeping; that thread is completely isolated, and the timer is going to keep on firing every second. Actually, the timer fires every second even if you move the Sleep(3000) into c().
What you have currently is:
1000 tick (start thread A)
2000 tick (start thread B)
3000 tick (start thread C)
4000 tick (start thread D, A prints line)
5000 tick (start thread E, B prints line)
6000 tick (start thread F, C prints line)
7000 tick (start thread G, D prints line)
8000 tick (start thread H, E prints line)
...
It is unclear what you are trying to do. You could disable the timer when you don't want it firing, and resume it again once ready, but it is unclear what the purpose of the Sleep() is here. Another option is just a while loop with a Sleep() in it. Simple, and doesn't involve lots of threads.

Every second you're starting new thread with 3 sec delay. It happens like this:
thread 1 start
thread 2 start, thread 1 sleeps
thread 3 start, thread 2 sleeps, thread 1 sleeps
thread 4 start, thread 3 sleeps, thread 2 sleeps, thread 1 sleeps
thread 5 start, thread 4 sleeps, thread 3 sleeps, thread 2 sleeps, thread 1 dumps
thread 6 start, thread 5 sleeps, thread 4 sleeps, thread 3 sleeps, thread 2 dumps
thread 7 start, thread 6 sleeps, thread 5 sleeps, thread 4 sleeps, thread 3 dumps
As you can see, each thread sleeps for 3 seconds, yet a dump occurs every second.
How do one works with threads? smth like this:
void Main()
{
new Thread(() => doWork()).Start();
Console.ReadLine();
}
public void doWork()
{
int h = 0;
do
{
Thread.Sleep(3000);
h.Dump();
h++;
}while(true);
}

Your example is very interesting - it shows the side effects of parallel processing. To answer your question, and to make it easier to see the side effects, I've slightly modified your example:
using System;
using System.Threading;
using System.Diagnostics;
public class Program
{
public static void Main()
{
(new Example()).Main();
}
}
public class Example
{
public void Main()
{
System.Timers.Timer t = new System.Timers.Timer(10);
t.Enabled = true;
t.Elapsed += (sender, args) => c();
Console.ReadLine(); t.Enabled = false;
}
int t = 0;
int h = 0;
public void c()
{
h++;
new Thread(() => doWork(h)).Start();
}
public void doWork(int h2)
{
Stopwatch sw = new Stopwatch();
sw.Start();
try
{
t++;
Console.WriteLine("h={0}, h2={1}, threads={2} [start]", h, h2, t);
Thread.Sleep(3000);
}
finally
{
sw.Stop();
var tim = sw.Elapsed;
var elapsedMS = tim.Seconds * 1000 + tim.Milliseconds;
t--;
Console.WriteLine("h={0}, h2={1}, threads={2} [end, sleep time={3} ms] ", h, h2, t, elapsedMS);
}
}
}
What I've modified here is the following:
Timer interval is now 10 ms, the threads still have 3000 ms. The effect is that while threads are sleeping, new threads will be created
I've added varialbe t, which counts the number of threads currently being active (it is increased when the thread starts and decreased right before the thread ends)
I've added 2 dump statements, printing out the thread start and the thread end
Finally, I've given the parameter of function doWork a different name (h2), which allows to see the value of the underlying variable h
Now it is intersting to see the output of this modified program in LinqPad (note the values are not always the same as they're depending on the race conditions of the started threads):
h=1, h2=1, threads=1 [start]
h=2, h2=2, threads=2 [start]
h=3, h2=3, threads=3 [start]
h=4, h2=4, threads=4 [start]
h=5, h2=5, threads=5 [start]
...
h=190, h2=190, threads=190 [start]
h=191, h2=191, threads=191 [start]
h=192, h2=192, threads=192 [start]
h=193, h2=193, threads=193 [start]
h=194, h2=194, threads=194 [start]
h=194, h2=2, threads=192 [end]
h=194, h2=1, threads=192 [end]
h=194, h2=3, threads=191 [end]
h=195, h2=195, threads=192 [start]
I think the values speak for themselves: What is happening is that every 10 ms a new thread is started, while others are still sleeping. Also interesting is to see that h is not always equal to h2, especially not if more threads are started while others are sleeping. The number of threads (variable t) is after a while stabilizing, i.e. running around 190-194.
You might argue, that we need to put locks on the variables t and h, for example
readonly object o1 = new object();
int _t=0;
int t {
get {int tmp=0; lock(o1) { tmp=_t; } return tmp; }
set {lock(o1) { _t=value; }}
}
While that is a cleaner approach, it didn't change the effect shown in this example.
Now, in order to prove that each thread really sleeps 3000ms (= 3s), let's add a Stopwatch to the worker thread doWork:
public void doWork(int h2)
{
Stopwatch sw = new Stopwatch(); sw.Start();
try
{
t++; string.Format("h={0}, h2={1}, threads={2} [start]",
h, h2, t).Dump();
Thread.Sleep(3000); }
finally {
sw.Stop(); var tim = sw.Elapsed;
var elapsedMS = tim.Seconds*1000+tim.Milliseconds;
t--; string.Format("h={0}, h2={1}, threads={2} [end, sleep time={3} ms] ",
h, h2, t, elapsedMS).Dump();
}
}
For a proper cleanup of the threads, let's disable the timer after the ReadLine as follows:
Console.ReadLine(); t.Enabled=false;
This allows you to see what happens if no more threads are starting, after you've pressed ENTER:
...
h=563, h2=559, threads=5 [end, sleep time=3105 ms]
h=563, h2=561, threads=4 [end, sleep time=3073 ms]
h=563, h2=558, threads=3 [end, sleep time=3117 ms]
h=563, h2=560, threads=2 [end, sleep time=3085 ms]
h=563, h2=562, threads=1 [end, sleep time=3054 ms]
h=563, h2=563, threads=0 [end, sleep time=3053 ms]
You can see they are all being terminated one after the other as expected and they slept about 3s (or 3000ms).

The reason you see this behavior is simple: you schedule a new thread each second, with the result becoming visible three seconds later. You do not see anything for the first four seconds; then, the thread that has been started three seconds ago dumps; another thread will have been sleeping for two seconds by then, and yet another - for one second. The next second thread #2 dumps; then thread #3, #4, and so on - you get a printout every second.
If you would like to see a printout every three seconds, you should schedule a new thread every three seconds with any delay that you would like: the initial thread will output in three seconds plus the delay; all the subsequent threads will be firing on three-second intervals.

Seems like you are runing a new thread every second wich is not a good idea, use backgroundworker, and when the event backgroundworker completed call the C function again, that way you wont need a timer

Each doWork is sleeping for three seconds, but their sleeps overlap because you create the threads at one second intervals.

Related

Is there a way to ignore the Thread Sleep for a certain function?

So I am currently developing a C# Forms App, and in that Forms App I have a Backgroundworker that loops through a list with DataGridViewRow's, and creates a Thread for each Row. In that Thread, I sleep the program for as long as the user inputs, but I would like to update a string in that Thread while the Thread is sleeping, so basically prevent one function from sleeping inside the Thread itself. Is that possible?
I appreciate any help!
Here's an example of calling a task that says "Hello", then sleeps for 5 seconds, then says "Goodbye". But while it's sleeping, it starts another task that does a simple countdown.
Maybe this will be helpful to you:
private static void Main()
{
var sleepTime = TimeSpan.FromSeconds(5);
var sleepyTask = Task.Factory.StartNew(() =>
{
Console.WriteLine("I'm going to sleep");
// Before sleeping, launch a countdown timer
Task.Factory.StartNew(() =>
{
Countdown(sleepTime);
});
// Now go to sleep
Thread.Sleep(sleepTime);
Console.WriteLine("I'm back!");
});
sleepyTask.Wait();
GetKeyFromUser("\nDone! Press any key to exit...");
}
private static void Countdown(TimeSpan time)
{
var seconds = time.TotalSeconds;
// Write something once per second for 'seconds' seconds
while (seconds > 0)
{
Console.WriteLine(seconds--);
Thread.Sleep(TimeSpan.FromSeconds(1));
}
}

c# run a thread each one minute despite the thread time

I want to run a process every one minute, but I have been told that the Timer is working every x minute + the time required for the process to finish. but I want the thread to work every 1 minute even though the thread process may keep working for 1 hour.
I hope you got me, so in the final image, I may have 10 threads working together.
is that possible ?
Depends on the timer. Simple test shows that System.Threading.Timer works the way you want:
var timer = new Timer(s => { "Start".Dump(); Thread.Sleep(10000); "Hi!".Dump(); },
null, 1000, 1000);
Thread.Sleep(20000);
timer.Dump();
The callback executes every second even though it takes ten seconds to execute.
This is basically because the callback for this particular timer is simply posted to the threadpool, while e.g. System.Windows.Forms.Timer is actually tied to the UI thread. Of course, if you simply start a new thread (or queue work, or start a new task etc.) in the callback of winforms timer, it will work in a similar (albeit less precise) way.
Using the right tool for the job usually makes things much easier :)
Create a Timer and on the elapse event just fire a new thread to do the work, like the below example:
public class Example
{
private static Timer aTimer;
public static void Main()
{
// Create a timer with a two second interval.
aTimer = new Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program... ");
Console.ReadLine();
Console.WriteLine("Terminating the application...");
}
public static void DoWork()
{
var workCounter = 0;
while (workCounter < 100)
{
Console.WriteLine("Alpha.Beta is running in its own thread." + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
workCounter++;
}
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
// Create the thread object, passing in the method
// via a delegate.
var oThread = new Thread(DoWork);
// Start the thread
oThread.Start();
}
}
Since .NET 4.0 Tasks are preferred to Threads.
The overhead of Task management is minimal.
// Create a task spawning a working task every 1000 msec
var t = Task.Run(async delegate
{
while (isRunning)
{
await Task.Delay(1000);
Task.Run(() =>
{
//your work
};
}
});

Thread execution order

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

ASP.NET/C# Events difference

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

What is the difference between ManualResetEvent and AutoResetEvent in .NET?

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.

Categories

Resources