AutoResetEvent clarification - c#

I want to clarify how the following code works.I have itemized my doubts to get your reply.
class AutoResetEventDemo
{
static AutoResetEvent autoEvent = new AutoResetEvent(false);
static void Main()
{
Console.WriteLine("...Main starting...");
ThreadPool.QueueUserWorkItem
(new WaitCallback(CodingInCSharp), autoEvent);
if(autoEvent.WaitOne(1000, false))
{
Console.WriteLine("Coding singalled(coding finished)");
}
else
{
Console.WriteLine("Timed out waiting for coding");
}
Console.WriteLine("..Main ending...");
Console.ReadKey(true);
}
static void CodingInCSharp(object stateInfo)
{
Console.WriteLine("Coding Begins.");
Thread.Sleep(new Random().Next(100, 2000));
Console.WriteLine("Coding Over");
((AutoResetEvent)stateInfo).Set();
}
}
static AutoResetEvent autoEvent = new AutoResetEvent(false);
At initial stage signal is set to false.
ThreadPool.QueueUserWorkItem(new WaitCallback(CodingInCSharp), autoEvent);
Select a thread from ThreadPool and make that thread to execute CodingInCSharp.
The purpose of WaitCallback is to execute the method after Main() thread
finishes its execution.
autoEvent.WaitOne(1000,false)
Wait for 1 sec to get the signal from "CodingInCSharp")
Incase if i use WaitOne(1000,true), will it kill the thread it received from
threadpool?
If I did not set ((AutoResetEvent)stateInfo).Set(); will the Main() indefinitely wait for signal?

The WaitCallback is executed in concurrently to the Main method as soon as a threadpool thread becomes available.
The Main method waits 1 second for the CodingInCSharp method on the threadpool thread to set the signal. If the signal is set within 1 second, the Main method prints "Coding singalled(coding finished)". If the signal is not set within 1 second, the Main method aborts waiting for the signal and prints "Timed out waiting for coding". In both cases the Main method proceeds to wait for a key to be pressed.
Setting a signal or reaching a timeout does not "kill" a thread.
The Main method will not wait indefinitely if the signal is not set, because waiting for the signal is aborted if the signal is not set within 1 second.

Related

AutoResetEvent accumulative Sets()

I've written this code as proof of concept in order to check a problem I'm experimenting with my current project.
var sleeper = new AutoResetEvent(false);
sleeper.Set();
sleeper.Set();
sleeper.Set();
var ix = 0;
while(true) {
sleeper.WaitOne();
Console.Write(ix++);
}
Surprisingly (at least for me) I'm not getting the result I expected.
I expected a 012 being printed in the console but only 0 is printed.
What am I misunderstanding ?
Which might be the best way to solve this problem and get the expected result?
Actually output for your code is 0
AutoResetEvent does not have a memory, it is either signalled or not. And you're waiting on it after it has been signalled. The sequence of events in your case:
create AutoResetEvent (state = 0)
signal AutoResetEvent (state = 1)
signal AutoResetEvent (state = 1)
signal AutoResetEvent (state = 1)
start waiting on the event (process the current signalled state of 1 and switch it to 0)
go on waiting on the event
As mentioned in msdn AutoResetEvent description
Also, if Set is called when there are no threads waiting and the
AutoResetEvent is already signaled, the call has no effect.
To observe the desired behavior you need a second Thread (as AutoResetEvent is created for inter-thread communication).
Something like this should work for you
private static AutoResetEvent sleeper;
static void Main()
{
sleeper = new AutoResetEvent(false);
Thread t = new Thread(ThreadProc);
t.Start();
var ix = 0;
while(true)
{
sleeper.WaitOne();
Console.Write(ix++);
}
}
static void ThreadProc()
{
Thread.Sleep(1000);
sleeper.Set();
Thread.Sleep(1000);
sleeper.Set();
Thread.Sleep(1000);
sleeper.Set();
}
Please note, that AutoResetEvent does not guarantee that it' will process 3 events for the following code
sleeper.Set();
sleeper.Set();
sleeper.Set();
as mentioned in its' description
Hence the Thread.Sleep(1000) bits.
There is no guarantee that every call to the Set method will release a
thread. If two calls are too close together, so that the second call
occurs before a thread has been released, only one thread is released.
It is as if the second call did not happen.

Communicate to the UI thread when a thread completes

I have a simple program here below that has 2 threads performing some task.
Thread1 is the data feeder. Thread2 is the data processor.
So far the work being done through my approach is working but I want to have better way of getting notified when the work completes
Here is the code
class Program
{
private static BlockingCollection<int> _samples = new BlockingCollection<int>();
private static CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
private static bool _cancel;
static void Main(string[] args)
{
ThreadStart thread1 = delegate
{
ProcessThread1();
};
new Thread(thread1).Start();
ThreadStart thread2 = delegate
{
ProcessThread2();
};
new Thread(thread2).Start();
Console.WriteLine("Press any key to cancel..");
Console.Read();
_cancel = true;
_cancellationTokenSource.Cancel();
Console.Read();
}
private static void ProcessThread1()
{
for (int i = 0; i < 10; i++)
{
if (_cancel)
{
break;
}
Console.WriteLine("Adding data..");
_samples.TryAdd(i,100);
Thread.Sleep(1000);
}
// I dont like this. Instead can I get notified in the UI thread that this thread is complete.
_cancel = true;
_cancellationTokenSource.Cancel();
}
private static void ProcessThread2()
{
while (!_cancellationTokenSource.IsCancellationRequested)
{
int data;
if (_samples.TryTake(out data, 100))
{
// Do some work.
Console.WriteLine("Processing data..");
}
}
Console.WriteLine("Cancelled.");
}
}
I want the program to exit if the cancel is requested by the user or when the work completes.
I am not sure how I can get notified when the ProcessThread1 runs out of work. Currently I am setting cancel = true when the work is complete but it seem not right. Any help appreciated.
If you use Task instead of manually creating threads, you can attach a continuation on your task to notify your UI that the work is complete.
Task workOne = Task.Factory.StartNew( () => ProcessThread1());
workOne.ContinueWith(t =>
{
// Update UI here
}, TaskScheduler.FromCurrentSynchronizationContext());
With .NET 4.5, this becomes even easier, as you can potentially use the new async language support:
var workOne = Task.Run(ProcessThread1);
var workTwo = Task.Run(ProcessThread2);
// asynchronously wait for both tasks to complete...
await Task.WhenAll(workOne, workTwo);
// Update UI here.
Note that these both are designed with a user interface in mind - and will behave unusually in a console application, as there is no current synchronization context in a console application. When you move this to a true user interface, it will behave correctly.
Start one more thread whose only job is to wait on console input:
private void ConsoleInputProc()
{
Console.Write("Press Enter to cancel:");
Console.ReadLine();
_cancellationTokenSource.Cancel();
}
Your main thread then starts the two processing threads and the input thread.
// create and start the processing threads
Thread t1 = new Thread(thread1);
Thread t2 = new Thread(thread2);
t1.Start();
t2.Start();
// create and start the input thread
Thread inputThread = new Thread(ConsoleInputProc);
inputThread.Start();
Then, you wait on the two processing threads:
t1.Join();
// first thread finished. Request cancellation.
_cancellationTokenSource.Cancel();
t2.Join();
So if the user presses Enter, then the input thread sets the cancellation flags. thread1 and thread2 both see the cancellation request and exit.
If thread1 completes its work, then the main thread sets the cancellation flag and thread2 will cancel.
In either case, the program won't exit until thread 2 exits.
There's no need to kill the input thread explicitly. It will die when the program exits.
By the way, I would remove these lines from the thread 1 proc:
// I dont like this. Instead can I get notified in the UI thread that this thread is complete.
_cancel = true;
_cancellationTokenSource.Cancel();
I would remove the _cancel variable altogether, and have the first thread check IsCancellationRequested just like the second thread does.
It's unfortunate that you have to start a dedicated thread to wait on console input, but it's the only way I know of to accomplish this. The Windows console doesn't appear to have a waitable event.
Note that you could do this same thing with Task, which overall is easier to use. The code that the tasks perform would be the same.
Update
Looking at the bigger picture, I see that you have a typical producer/consumer setup with BlockingCollection. You can make your producer and consumer threads a lot cleaner:
private static void ProcessThread1()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Adding data..");
_samples.TryAdd(i, Timeout.Infinite, _cancellationTokenSource.Token);
// not sure why the sleep is here
Thread.Sleep(1000);
}
// Marks the queue as complete for adding.
// When the queue goes empty, the consumer will know that
// no more data is forthcoming.
_samples.CompleteAdding();
}
private static void ProcessThread2()
{
int data;
while (_samples.TryTake(out data, TimeSpan.Infinite, _cancellationTokenSource.Token))
{
// Do some work.
Console.WriteLine("Processing data..");
}
Console.WriteLine("Cancelled.");
}
You'll still need that input thread (unless you want to spin a loop on Console.KeyAvailable), but this greatly simplifies your producer and consumer.

Proper Way to Stop App While Threads Are Waiting on WaitOne()

I'm playing around with AutoResetEvent and my app isn't ending, and I think I know why: the threads are still running and therefore the app won't terminate. Normally, in Main(), after I press a key, the app terminates. But the console window no longer closes. I have a simple console app:
private static EventWaitHandle waitHandle = new AutoResetEvent(false);
static void Main(string[] args)
{
AutoResetEventFun();
Console.WriteLine("Press any key to end.");
Console.ReadKey();
waitHandle.Close(); // This didn't cause the app to terminate.
waitHandle.Dispose(); // Nor did this.
}
private static void AutoResetEventFun()
{
// Start all of our threads.
new Thread(ThreadMethod1).Start();
new Thread(ThreadMethod2).Start();
new Thread(ThreadMethod3).Start();
new Thread(ThreadMethod4).Start();
while (Console.ReadKey().Key != ConsoleKey.X)
{
waitHandle.Set(); // Let one of our threads process.
}
}
// There are four of these methods. Only showing this one for brevity.
private static void ThreadMethod1()
{
Console.WriteLine("ThreadMethod1() waiting...");
while (true)
{
waitHandle.WaitOne();
Console.WriteLine("ThreadMethod1() continuing...");
}
}
What's the right way to terminate this app? Do I need to retain a reference to each thread and call Abort() on each one? Is there a way to signal waitHandle so that the threads waiting on it will terminate? (I don't think so, but I thought it would be worth asking.)
While I'm not entirely sure what you're trying to accomplish, one way to have this app terminate is to make all thread background threads:
private static void ThreadMethod1()
{
Thread.CurrentThread.IsBackground = true;
Console.WriteLine("ThreadMethod1() waiting...");
while (true)
{
waitHandle.WaitOne();
Console.WriteLine("ThreadMethod1() continuing...");
}
}
Another way is to set a volatile 'Abort' boolean flag that the threads always check after returning from the WaitOne() call to see if they need to exit. You could then set this flag and signal the WaitHandle [no. of threads] times.

C# Threading - How to start and stop a thread

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

Waiting the main thread to stop until a task is processed by an async thread

Lets say we have a following program where in its Start method, it delegates some long running task to another thread. When the Stop method is called, i need to make sure that worker thread completes executing the current task and does not leave it in the middle of it. If it has already completed the task and is in sleep state, then it can stop immidiately.
Please guide me on how should I do it.
static int itemsProcessed = 0;
static Thread worker;
static void Start()
{
var ts = new ThreadStart(Run);
worker = new Thread(ts);
worker.Start();
}
static void Stop()
{
//wait until the 'worker' completes processing the current item.
Console.WriteLine("{0} Items Processed", itemsProcessed);
}
static void Run(object state)
{
while (true)
{
ALongRunningTask();
itemsProcessed++;
Thread.Sleep(1000);
}
}
One way to do this is to use a volatile variable to communicate betweej the two threads. To do this, create a "volatile bool isRunning;". In Start set the value to true, then in Run chage your while loop to "while (isRunning)". In stop, set isRunning equal to false and then call worker.Join(). This will cause your run method to exit when it finishes processing the current item, and Join will wait until the thread exits.
The last thing you need to do is to access itemsProcessed in a thread-safe way. In the current code there is no way to know if Stop sees the most up to date value of itemsProcessed since it was changed from another thread. One option would be to create a lock for itemsProcessed and hold the lock inside of Run, and acquire the lock before the WriteLine statement in Stop.
Assuming you always want the long running task thread as a whole to finish, you could just wait till the thread is done by calling Thread.Join();
If you want to finish work in your thread gracefully you must do some sort of message passing, in the most simple case it could be just a boolean - in your case there seems to be just one thread, so it can be a static variable (simplifying here as much as possible)
static volatile bool processing = true;
static void Stop()
{
processing = false;
//wait until the 'worker' completes processing the current item.
worker.Join();
Console.WriteLine("{0} Items Processed", itemsProcessed);
}
static void Run(object state)
{
while (proccessing)
{
ALongRunningTask();
itemsProcessed++;
}
}

Categories