Thread.Join() changes program output in C# - c#

This is a slightly modified version of one of the sample programs give in C# in a Nutshell :
using System;
using System.Threading;
namespace SemaphorTest
{
class Program
{
static Semaphore gate = new Semaphore(3, 3);
static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
Thread t = new Thread(Enter);
t.Start(i);
}
}
public static void Enter(Object id)
{
Console.WriteLine("Thread " + id + " wants to enter.");
gate.WaitOne();
Console.WriteLine("Thread " + id + " is in.");
Thread.Sleep(500 * (Int32)id);
Console.WriteLine("Thread " + id + " leaving.");
gate.Release();
}
}
}
This prints the following output (seemingly in random order) :
Thread 0 wants to enter.
Thread 1 wants to enter.
Thread 1 is in.
Thread 0 is in.
Thread 2 wants to enter.
Thread 3 wants to enter.
Thread 0 leaving.
Thread 3 is in.
Thread 4 wants to enter.
Thread 2 is in.
Thread 1 leaving.
Thread 4 is in.
Thread 2 leaving.
Thread 3 leaving.
Thread 4 leaving.
However, adding a Thread.Join() as follows changes the output drastically.ie:
for (int i = 0; i < 5; i++)
{
Thread t = new Thread(Enter);
t.Start(i);
t.Join();
}
Changes the output to :
Thread 0 wants to enter.
Thread 0 is in.
Thread 0 leaving.
Thread 1 wants to enter.
Thread 1 is in.
Thread 1 leaving.
Thread 2 wants to enter.
Thread 2 is in.
Thread 2 leaving.
Thread 3 wants to enter.
Thread 3 is in.
Thread 3 leaving.
Thread 4 wants to enter.
Thread 4 is in.
Thread 4 leaving.
Why does this happen ? I know that these threads are foreground threads by default and that the Main thread doesn't need to wait for them to complete (they will run even after Main completes so they won't require a thread.Join() here). But I don't understand what makes them run in the order as they were created after the change. Any ideas ?
Thanks
Dileep Balakrishnan

Why does this happen?
Because you've asked it to!
You've started one thread, then waited for it to finish, then started the next thread etc. That's precisely what Thread.Join does: it blocks the currently executing thread until the thread you've called it on terminates.
What I'm interested in is what you expected that code to do... If you just wanted to wait until all the threads had finished before letting the main thread complete, you need to start all the threads, remembering them as you go, and then call Join on each on in turn. For example:
List<Thread> threads = new List<Thread>();
// First start all the threads
for (int i = 0; i < 5; i++)
{
Thread t = new Thread(Enter);
t.Start(i);
threads.Add(t);
}
// Then wait for them to finish
foreach (var thread in threads)
{
thread.Join();
}

You are joining each thread with the calling thread. This will essentially block the calling thread and wait for each thread to end in turn.
In the documentation it states:
Blocks the calling thread until a thread terminates.

Thread.join() does not make things run concurrently. It actually enforces the behaviour you're seeing by blocking the current thread until it's completed.
This is mentioned clearly in the documentation: http://msdn.microsoft.com/en-us/library/95hbf2ta.aspx

Related

Not getting expected output in the Multithreading question

Task description:
Write a program that reads an positive integer value n (n > 3), then
creates n threads (each thread has id; id starts from 1) and works
until it receives a stop signal. All of n threads are waiting for a
signal. Every second main thread sends a signal for a random thread,
then that thread should print its id and return to a waiting state.
Requirements:
All additional threads should be finished correctly. At the thread
function exit, a message about exit should be printed. While the
thread is waiting for the condition variable, spurious wakeup should
be checked. Only std::cout allowed for text output. Stop signal is
SIGINT (ctrl+c).
I have written the following code for the above question but in output, all the threads are not exiting. I am not able to figure out the problem as I am new to this topic. Any kind of help will be really appreciated.
class Program
{
public static void Main()
{
var numberofthreads = Convert.ToInt32(Console.ReadLine());
ProcessingClass myobject = new ProcessingClass();
myobject.createThreads(numberofthreads);
}
}
public class ProcessingClass
{
public Mutex mymutex = new Mutex();
private bool thread_flag = false;
public void createThreads(int numberofthreads)
{
var threads = new List<Thread>(numberofthreads);
for (int i = 0; i < numberofthreads; i++)
{
Thread th = new Thread(() =>
{
threadsworking();
});
th.Name = "Thread" + i;
th.Start(); // <-- .Start() makes the thread start running
threads.Add(th);
}
Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) =>
{
var isCtrlC = e.SpecialKey == ConsoleSpecialKey.ControlC;
if (isCtrlC)
{
thread_flag = true;
int num = 1;
foreach (var thread in threads)
{
thread.Join();
Console.WriteLine($"Thread {num} exits");
num++;
}
}
e.Cancel = true;
};
}
public void threadsworking()
{
while (thread_flag == false)
{
mymutex.WaitOne(); // Wait until it is safe to enter.
Console.WriteLine("{0}", Thread.CurrentThread.Name);
Thread.Sleep(1000); // Wait until it is safe to enter.
mymutex.ReleaseMutex(); // Release the Mutex.
}
}
}
enter image description here
Consider preventing mutex from blocking threads from exiting.
When you use mutex.WaitOne() it blocks execution until the Mutex is owned by that thread. This can be really helpful for ensuring a thread has exclusive control over a shared resource. However, where this becomes a problem is when you want to arbitrarily end those threads such as when you invoke the event on the Console.CancelKeyPress.
You can see the effects of this by logging before and after the thread.Join() call you do in the event.
thread_flag = true;
int num = 1;
foreach (var thread in threads)
{
Console.WriteLine($"Joining {thread.Name}");
thread.Join();
Console.WriteLine($"Joined {thread.Name}");
Console.WriteLine($"Thread {num} exits");
num++;
}
When we do that logging it will show us that when you call Join() on Thread # 1 you see Joining 1. Then there is a really long pause, other threads still are doing work, and then finally all the threads join back to back.
The reason for this is - while Join() is waiting for Thread 1 to finish, Thread 1 is still waiting for the mutex.
Even though you set the thread_flag flag to true, Thread 1 can't exit because it hasn't taken ownership of the mutex to perform it's work and eventually exit the while() loop.
We can solve this issue fairly simply.
Consider using a timeout when waiting for the mutex
When you call .WaitOne(n) on the mutex you can wait for n given milliseconds and give up taking ownership of the mutex.
This will allow more frequent evaluations of the while loop, and subsequently more times that the threadsworking method checks to see if it should exit(using the thread_flag flag).
Heres a short example how implementing that change might look
public void threadsworking()
{
while (thread_flag == false)
{
// wait to enter the mutex, give timeout to prevent blocking
// until mutex opens and use the bool returned to determine
// if we should release the mutex or not
if (mymutex.WaitOne(1))
{
try
{
Console.WriteLine("{0}", Thread.CurrentThread.Name);
Thread.Sleep(1000); // Wait until it is safe to enter.
}
finally
{
// make sure even if we encounter an error the mutex is released
mymutex.ReleaseMutex(); // Release the Mutex.
}
}
// allow other threads to continue their work instead of blocking with a while loop, this is optional depending on the workload
Thread.Yield();
}
}

C# Multi-Threading - What's wrong, how to use AutoResetEvent

I'm still learning Threading, and I have problems with this code below. Sorry if this question appeared before, I just don't really understand why this code not working.
I simplified the code:
static EventWaitHandle waitH; // AutoResetEvent, wait for signal
static bool whExit; // signal to exit waiting
static Queue<string> str; // waiting line (example values)
static Queue<int> num; //
static void Main(string[] args)
{
waitH = new AutoResetEvent(false); // initialize waiter
str = new Queue<string>();
num = new Queue<int>();
Thread thr = new Thread(new ThreadStart(Waiter)); // waiting in another thread
thr.Start(); // start the waiting thread
for(short i = 0; i < 10; i++)
{
str.Enqueue(string.Format($"{(char)(i + 65)}")); // add something to queue
num.Enqueue(i); // add a number to test incrementing
waitH.Set(); // signal to start the "long processing"
}
}
static void Waiter()
{
while(!whExit)
{
waitH.WaitOne(); // wait for signal
WriteToConsole(); // start the long processing on another thread
}
}
static void WriteToConsole()
{
// threadstart with parameters
// action: void delegate
// get 2 values from waiting line
var f = new ParameterizedThreadStart(obj =>
new Action<string, int>(ConsoleWriter)
(str.Dequeue(), num.Dequeue())); // it's thread safe, because FIFO?
Thread thr = new Thread(f);
thr.IsBackground = true; // close thread when finished
thr.Start();
}
// print to console
static void ConsoleWriter(string s, int n)
{
Console.WriteLine(string.Format($"{s}: {++n}")); // easy example
}
It stops in the Main's loop.
I think the problem is: Thread.Start() called first, but it needs to change of state of Thread and joins the "need to be processed" queue , which takes time. The Main's loop already running and not wait for the signaling.
I solved this problem with Two-way signaling: used another pause-signal AutoResetEvent after waitH.Set() in the loop (WaitOne) and signal it after finished Console.WriteLine().
I'm not really proud of this solution, because if I do so, the program looses the "threadish", parallel, or synchronous approach.
And this is an example, I would like to run long calculations at the same time, on different threads.
If I see the output, it's a book-fitting example that I'm doing it wrong:
Output:
A: 1
B: 2
Sometimes
B: 2
A: 1
Expected output:
A: 1
B: 2
C: 3
D: 4
E: 5
F: 6
G: 7
H: 8
I: 9
J: 10
Is there any elegant way to solve this? Maybe to use locks, etc.
Any discussion would be appreciated.
Thanks!
There are several issues:
The main method never waits for the worker thread to complete, so it will probably run to completion and stop all the threads before they are done. This could be solved by signaling the worker thread to stop, and then use thread.Join() to wait for it to complete.
The WriteToConsole takes one item from each list and prints it to the console. But the thread might start after the loop in the main method has completed. So when the thread starts the autoReset event will be signaled and one item will be processsed. But in the next iteration the autoResetEvent will be unsignaled, and will never become signaled again. This can be solved by iterating over all items in the queue after the event has been signaled.
Using two-way signaling in the loop like you mention will in effect serialize the code, removing any benefit of using threads.
If this is a learning exercise i would suggest spending the time learning Tasks, async/await, lock and Parallel.For first. If you have a good grasp of these things you will be much more effective than using threads and reset events by hand.
// it's thread safe, because FIFO?
No. Use the concurrent collections if you want threadsafe collections.

ManualResetEvent and CancellationToken to stop thread until others are done

I have a function which is going to be processed by like 5 threads at same time but with different arguments passed. I want to wait to make the main thread wait for the rest threads and then release it. I'm not even sure if CancellationToken would work with Threadpool because all examples are with Tasks and I want to set up a button to stop threads at some point.
I'm aware of the fact there is a lot of information about threading but that's the actual problem. I don't know which threading classes are better or how to implement them because there are ambiguous examples. One source says that it should be done in one way and another in other way. Here are some examples that I saw. You can see that MSDN's example is ambiguous compared to the other 2 links or at least I'm missing the point. https://jeremylindsayni.wordpress.com/2016/03/26/how-to-use-manualresetevent-in-c-to-block-one-thread-until-another-has-completed/, How to make main thread to wait until other threads ends and https://learn.microsoft.com/en-us/dotnet/api/system.threading.manualresetevent?view=netframework-4.7.2.
private void DoJob(object state)
{
Console.WriteLine("Delaying...");
Thread.Sleep(3000);
Console.WriteLine("Thread done");
_manualResetEvent.Set();
}
// on some button click event
_manualResetEvent = new ManualResetEvent(false);
for (int i = 0; i < threadsNumericUpDown.Value; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(DoJob), i);
}
_manualResetEvent.WaitOne();
Console.WriteLine("Main thread released");
In the example above, I wanted to make main thread wait for rest threads until they are done but the main thread is getting released after the first thread is done.
Delaying...
Delaying...
Delaying...
Delaying...
Thread done
Main thread released
Thread done
Thread done
Thread done
If I put WaitOne in each thread (DoJob method) and Set on the place of current WaitOne, the main thread is being released first and what I want is to release it after all other threads are done.
In your case, you really just use tasks:
var tasks = new List<Task>();
for (int i = 0; i < threadsNumericUpDown.Value; i++)
{
tasks.Add(Task.Run(() => DoJob(i)));
}
Task.WaitAll(tasks);
If for some reason you don't want to use tasks, you can have a look at CountdownEvent, which is precisely designed to wait on a definite number of asynchronous operations:
private void DoJob(object state)
{
Console.WriteLine("Delaying...");
Thread.Sleep(3000);
Console.WriteLine("Thread done");
_countdownEvent.Signal();
}
// on some button click event
_countdownEvent = new CountdownEvent(threadsNumericUpDown.Value);
for (int i = 0; i < threadsNumericUpDown.Value; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(DoJob), i);
}
_countdownEvent.Wait();
Console.WriteLine("Main thread released");

C# Thread and lock

I test simple code
static Thread _readThread = null;
static private Object thisLock = new Object();
static int a = 1;
private static void ReadComPort()
{
lock (thisLock)
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine(Thread.CurrentThread.Name + " " + a++.ToString());
Thread.Sleep(1000);
}
}
}
static void Main(string[] args)
{
for (int i = 0; i < 3; i++)
{
_readThread = new Thread(new ThreadStart(ReadComPort));
_readThread.IsBackground = true;
_readThread.Name = i.ToString();
_readThread.Start();
//Thread.Sleep(50);
}
Console.WriteLine("End");
Console.ReadKey();
}
but why is the sequence of execution and the launching of threads chaotic:
0,2,1 Why?
Console output:
0 1
End
0 2
0 3
2 4
2 5
2 6
1 7
1 8
1 9
Because you can't expect threads to start or run in a specific order. The OS schedules threads the way it wants to. Sometimes it puts a thread on hold, executes another one, before coming back to the original one.
Here you see that the threads start almost at the same time. Obviously (from the output) thread 0 wins it to the first lock. Then, by pure chance, thread 2 gets by the lock earlier than thread 1. This could have gone entirely different since the threads are created shortly after each other. As said: there is no guarantee.
Lock does not guarantee the order : Does lock() guarantee acquired in order requested?
Also, in your code, you should wait your threads to finish at the end of your for loop in order to not have "end" at the beginning - if you press a key, you will exit while your thread are still running, and you may have unexpected behaviour.
Read the C# reference carefully.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement
There, you cannot find anything about the order of threads entering the lock block.

ManualResetEventSlim Wait() doesn't work after Set() is done once

What I want to do
I have some threads (e.g. Thread 1, Thread 2, Thread 3), and a queue of integers (e.g. 1, 2, 3).
Every one second, I want to pause currently running thread, and pop from a queue, and run a thread that has the same id.
For example:
Let's say I have an array of thread, and an integer that holds currently executing thread.
int[] myThread; //1, 2, 3
ManualResetEventSlim[] mre;
executing = 1;
Queue myQueue; //2, 3
Time 0:01 //Thread 1 is running
Time 0:02 mre[executing].Wait();
myQueue.Enqueue(executing);
int nextThread = myQueue.Dequeue(); //say 2
mre[nextThread].Set();
executing = nextThread;
Time 0:03 //Same thing as at 0:02...
Time 0:04 //Same above
Time 0:05 //Same above
and want outputs that look like this:
Time 0:01 I'm 1
I'm 1
I'm 1
Time 0:02 I'm 2 // thread 2 was selected
I'm 2
I'm 2
Time 0:03 I'm 3 // thread 3 was selected
I'm 3
I'm 3
Time 0:04 I'm 2 // thread 2 was selected
I'm 2
I'm 2
What I'm doing
I have a main file that defines the action:
static void Main()
{
CreateThread(Action, n);
}
public static void Action(int pid)
{
for(int i=0; i<100000; i++)
{
Trace.WriteLine("I'm "+ pid);
}
}
Problem
The problem is that once a thread is set with Set(), it cannot be blocked again with Wait(). Because of that, each thread just keeps executing the whole Action method until it's done.
and outputs look like this:
Time 0:01 I'm 1 //Only Thread 1 is unblocked
I'm 1
I'm 1
Time 0:02 I'm 2 //Thread 2 was unblocked.
I'm 1 //Thread 1 is not blocked, so it keeps printing
I'm 2
Time 0:03 I'm 3 //Thread 3 was unblocked.
I'm 1 //Thread 1 is not blocked
I'm 2 //Thread 2 is not blocked either
I've been working on this for a while and am stuck. I really appreciate any help.
Im not sure if I understand the problem, but I'd change Action() so that it takes an instance of ThreadData. You'll need it to check whether the MRE is set. If so, break out of the iteration and let the framework take care of cleaning up after the thread.
public static void Action(ThreadData threadData)
{
for (int i = 0; i < 100000; i++)
{
if (threadData.Mre.IsSet)
{
break;
}
Trace.WriteLine("I'm " + threadData.Pid);
}
}
EDIT
You might not realize it, but you're probably using the same instance of MRE for each thread. Each thread references the mre variable. Who is to say that the thread starts before you set mre to a new instance? Spoiler: it doesn't.

Categories