C# Threading program | Regarding thread.join - c#

In the below program why the t.join functionality is not working. It will continue to type character O on the screen even when i have specified it to wait for the another thread to complete.
class Program
{
bool done;
static void Main(string[] args)
{
Thread t = new Thread(() => Go('U'));
for (int i = 0; i < 1000; i++)
{
Console.Write('O');
Thread.Sleep(500);
}
t.Start();
t.Join();
Console.WriteLine("Thread t has ended!");
Console.Read();
}
static void Go(char p)
{
for (int i = 0; i < 1000; i++)
{
Console.Write(p);
Thread.Sleep(500);
}
}
}

You never started the second thread - you're printing out Os, but you only start the second thread after you're done with that (in about eight minutes).
Move the t.Start(); before the loop, and it should work the way you expect it to work.
Don't guess around with multi-threading - it's incredibly easy to get subtly wrong. Learn what a thread is, what does Join do, and how to use multiple threads safely. Otherwise, you'll have a lot of fun debugging issues that are near impossible to reproduce and fix :)

Related

How to allow a thread to finish while another thread is sleeping

I am writing a C# Console Application that handles multiple threads, but for some of the threads I have to wait for some time while other threads are waiting to finish sleep time for the thread which is in sleep. So how can I achieve parallel programming when one thread is sleeping, but other threads should work at the same time?
A solution that I tried is below. The output which I'm expecting is as i == 1 is in sleep mode for 1 min till the time other two i == 2 and i == 3 should get printed in the meantime.
static void Main(string[] args)
{
for (int i = 0; i < 10; i++) {
if (i == 1) {
Console.WriteLine("1");
System.Threading.Thread.Sleep(60000);
}
else if (i == 2) {
Console.WriteLine("2");
}
else if (i == 3) {
Console.WriteLine("3");
}
}
}
OUTPUT
2
3
(after one minute) 1
Here is your simple solution:
static void Main(string[] args)
{
Task task = null;
for (int i = 0; i < 10; i++)
{
if (i == 1)
{
task = Task.Run(() => {
Thread.Sleep(60000);
Console.WriteLine("1");
}
);
}
else if (i == 2)
{
Console.WriteLine("2");
}
else if (i == 3)
{
Console.WriteLine("3");
}
}
task.Wait();
}
But I'm pretty sure that you need much more understanding, how the threads work. Good luck :)
As mjwills pointed out, you only have one thread here.
When you start an application, this will create one thread, usually it is called the main thread. To avoid your program from freezing you tend to try not to Thread.Sleep() in the main thread.
That being said when you want to create a new task which is similar to a thread you can process this way :
static void Main(string[] args)
{
Task yourTask = Task.Run( () => {
// Do Something, like your sleep.
});
yourTask.Wait();
}
If you want your task to run synchronously (for exemple you need to wait that something ends before you can continue your program), I suggest you see the RunSynchronously() method from the Task Class in the link above. If you want for it to run asynchronously (for example you don't need to wait that something ends before you can continue your program), you can check this link.
Hope this helps.
While I know this will downvoted, I can't help but point out the simplest solution to your problem is likely:
static void Main(string[] args)
{
Console.WriteLine("2");
Console.WriteLine("3");
System.Threading.Thread.Sleep(60000);
Console.WriteLine("1");
}
It gives the exact output you are aiming for. It is simple, and easy to read and understand. It doesn't use a loop or an extra thread - but the code in your question doesn't need either of those things.

Issue with thread barrier - PulseAll not reaching all threads

I have a parallel algorithm which I have some barrier issues with. Before y'all scream "search" I can say I have looked at available posts and links, and I have followed the instructions for a barrier with Monitor.Wait and Monitor.PulseAll, but my issue is that all threads except the last one created (and initiated) is reached by the PulseAll from my main thread. Here are how the basic layout of the code is:
public static object signal = new object(); //This one is located as class variable, not in the method
public void RunAlgorithm(List<City> cities){
List<Thread> localThreads = new List<Thread>();
object[] temp = //some parameters here
for(int i = 0; i < numOfCitiesToCheck; i++){
Thread newThread = new Thread((o) => DoWork(o as object[]));
newThread.IsBackground = true;
newThread.Priority = ThreadPriority.AboveNormal;
newThread.Start(temp as object);
localThreads.Add(newThread);
}
//All threads initiated, now we pulse all
lock(signal){
Monitor.PulseAll(signal);
}
int counter = 0;
while(true){
if(counter == localThreads.Count){ break; }
localThreads[counter].Join();
counter++;
}
}
That's what done by the main thread (removed a few uneccessary pieces) and as stated before the main thread will always get stuck in the Join() on the last thread in the list.
This is how the method of the threads look like:
private void DoWork(object[] arguments){
lock(signal){
Monitor.Wait(signal);
}
GoDoWork(arguments);
}
Are there any other barriers I can use for this type of signaling? All I want is to let the main thread signal all threads at the same time so that they start at the same time. I want them to start at the same time inorder to have as close parallel as possible (I measure running time for the algorithm and a few other things). Is there any part of my barrier or code that is flawed (with the barrier I mean)? I tried running an instance with fewer threads and it still get stuck on the last one, I don't know why it is. I have confirmed by via VS debug that the last thread is sleeping (all other threads are !isAlive, while the last one isAlive = true).
Any help appreciated!
I managed to solve it using the Barrier class. Many thanks to Damien_The_Unbeliever! Still can't believe I haven't heard of it before.
public Barrier barrier = new barrier(1);
public void RunAlgorithm(List<City> cities){
List<Thread> localThreads = new List<Thread>();
object[] temp = //some parameters here
for(int i = 0; i < numOfCitiesToCheck; i++){
barrier.AddParticipant();
Thread newThread = new Thread((o) => DoWork(o as object[]));
newThread.IsBackground = true;
newThread.Priority = ThreadPriority.AboveNormal;
newThread.Start(temp as object);
localThreads.Add(newThread);
}
barrier.SignalAndWait();
int counter = 0;
while(true){
if(counter == localThreads.Count){ break; }
localThreads[counter].Join();
counter++;
}
}
private void DoWork(object[] arguments){
barrier.SignalAndWait();
GoDoWork(arguments);
}

How Java and C# threads deal with data synchronisation differently?

In the following C# code, t1 always(for the times I tried) finishes.
class MainClass
{
static void DoExperiment ()
{
int value = 0;
Thread t1 = new Thread (() => {
Console.WriteLine ("T one is running now");
while (value == 0) {
//do nothing
}
Console.WriteLine ("T one is done now");
});
Thread t2 = new Thread (() => {
Console.WriteLine ("T two is running now");
Thread.Sleep (1000);
value = 1;
Console.WriteLine ("T two changed value to 1");
Console.WriteLine ("T two is done now");
});
t1.Start ();
t2.Start ();
t1.Join ();
t1.Join ();
}
public static void Main (string[] args)
{
for (int i=0; i<10; i++) {
DoExperiment ();
Console.WriteLine ("------------------------");
}
}
}
But in the Java code which is very similar, t1 never(for the times I tried) exits:
public class MainClass {
static class Experiment {
private int value = 0;
public void doExperiment() throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("T one is running now");
while (value == 0) {
//do nothing
}
System.out.println("T one is done now");
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("T two is running now");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
value = 1;
System.out.println("T two changed value to 1");
System.out.println("T two is done now");
}
}
);
t1.start();
t2.start();
t1.join();
t1.join();
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
new Experiment().doExperiment();
System.out.println("------------------------");
}
}
}
Why is that?
I'm not sure how it happens in C#, but what happens in Java is JVM optimization. The value of value does not change inside the while loop and the JVM recognises it and just skip the test and change your bite code to something like this:
while (true) {
// do nothing
}
In order to fix this in java you need to declare value as volatile:
private volatile int value = 0;
This will make the JVM to not optimise this while loop and check the for the actual value of value at the start of each iteration.
There are a couple of things here.
Firstly, when you do:
t1.Start ();
t2.Start ();
You're asking the operating system to schedule the threads for runnings. It's possible that t2 will start first. In fact it may even finish before t1 is ever scheduled to run.
However, there is a memory model issue here. Your threads may run on different cores. It's possible that value is sitting in the CPU cache of each core, or is stored in a register on each core, and when you read/write to value you are writing to the cache value. There's no requirement for the language runtime to flush the writes to value back to main memory, and there's no requirement for it to read the value back from main memory each time.
If you want to access a shared variable then it's your responsibility to tell the runtime that the variable is shared, and that it must read/write from main memory and/or flush the CPU cache. This is typically done with lock, Interlocked or synchronized constructs in C# and Java. If you surround access to value with a lock (in C#) or synchronized (in Java) then you should see consistent results.
The reason things behave differently without locking is that each language defines a memory model, and these models are different. Without going into the specifics, C# on x86 writes back to main memory more than the Java memory model does. This is why you're seeing different outcomes.
Edit: For more information on the C# side of things take a look at Chapter 4 of Threading in C# by Joseph Albahari.

In this simple multithreading example, why does the last method in Main() always execute last?

static int i = 0;
static void Main()
{
ThreadTest tt = new ThreadTest();
new Thread(tt.Incr).Start();
tt.I();
tt.I2();
}
void Incr()
{
for(int x = 0; x < 3; x++)
{
Console.WriteLine(i);
i++;
}
}
void I()
{
while(i <= 3)
{
if(i==3)
break;
Console.WriteLine("Value of i in I:{0}",i);
}
}
void I2()
{
Console.WriteLine("\t\tFinally i is:{0}\n\n",i);
}
I have run this piece of code about a few hundred times now and find that I2 always executes last. Why does this happen? May be a few hundred times is not enough to see the true unpredictability of threads?
Output of 11 runs
Well, I2() is the last method in Main() and it is not threaded in any way.
So what's the question, why the thread finishes earlier?
That's because I2() is run after I() and the while-loop in I() effectively waits for the thread to finish first.
The method I2 will always be executed last. This has nothing to do with threads.
static void Main()
{
ThreadTest tt = new ThreadTest();
new Thread(tt.Incr).Start();
tt.I(); // This will be executed first
tt.I2(); // This will be executed last
}
The flow of the newly started thread and the current thread is not synchronized, but the current thread will continiue its operation in a synchronous fashion executing statements in the order as the appear. In this case I() will be called before I2().

Threading in Mono

I am trying Mono/.Net 3.5 under Linux (Ubuntu). I tried to use threads in Mono, but it doesn't seem to work properly.
public static void Main (string[] args)
{
Thread thread =new Thread(()=> fn("first"));
Thread thread1=new Thread(()=> fn("second"));
thread.Start();
thread1.Start();
}
static void fn(string name)
{
for(int i=0;i<10;i++)
Console.WriteLine(i+" "+name);
}
Both loops run sequentially, as if I am not using threads.
What is wrong?
Running this on Windows, most of the time all the first thread's writes happen before the second thread's.
The loop is too trivial to really see the effects of multiple threads running concurrently. The first thread may simply finish before the second starts.
Try putting a Sleep or spin loop in the main loop.
for(int i=0; i<10; i++) {
Console.WriteLine(i+" "+name);
Thread.Sleep(10);
}
or
for(int i=0; i<10; i++) {
Console.WriteLine(i+" "+name);
for(int j=0; j<100000; j++);
}

Categories

Resources