Does thread.join starts all threads at the same time - c#

Thread[] threads = new Thread[12];
int temp;
//_stopRequest = false;
for (int i = 0; i < threads.Length - 1; i++)
{
temp = i;
threads[temp] = new Thread(new ThreadStart(() => test(test1[temp],"start", temp)));
threads[temp].Start();
//threads[temp].Join();
}
for(int i=0; i<threads.Length-1; i++)
{
threads[i].Join();
}
Can Anyone please explain me

No, the threads are started when you call Start().
If you would call Join() immediately after Start() (the commented-out code), each thread would be started and then execution of the current thread would be halted until the first thread stops. So it would actually have acted as a single thread.
The way the code is now, all threads are started and then the current thread waits for all the started threads to finish.

Related

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# Multi Thread and Read/Write large text file

I wan to speed up my tool with multi thread to read/write text file
Here how I start - I think I need 7 thread
for (int i = 0; i < 7; i++)
{
Thread thread = new Thread(() => process(files[i], i));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
And my func
void process(string file,int threadnumber)
{
// display thread number
// filter text
// read - write
}
But when I start:
Thread: 3 start
Thread: 3 start
Thread: 3 start
Thread: 4 start
Thread: 5 start
Thread: 6 start
Thread: 7 start
Why my tool don't start thread 1 2 3 4 5 6 7.. few threads duplicate - meaning read and write same file and error.
Please give me advise.
Depending on how fast the loop iterates and how fast a thread starts, there is a chance that by the time that a thread actually starts the i variable might have changed.
You must declare a new variable, for each thread, that is not changed:
for (int i = 0; i < 7; i++)
{
int j = i; //New variable set to the current 'i'.
Thread thread = new Thread(() => process(files[j], j));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
In the above the j-variable will get the same value as the current i, and won't change even if the loop continues to iterate.

Why Thread.Sleep synchronizes threads?

Why without Thread.Sleep threads will work asynchronously (1), and with it - synchronously (2)?
class A
{
static object locker = new object();
static void M0()
{
for(int i = 0; i < 5; i++)
lock (locker)
{
Console.WriteLine("Secondary");
//Thread.Sleep(100);
}
}
static void Main()
{
ThreadStart ts = new ThreadStart(M0);
Thread t = new Thread(ts);
t.Start();
for (int i = 0; i < 5; i++)
lock (locker)
{
Console.WriteLine("Primary");
//Thread.Sleep(100);
}
}
}
Both ways are working asynchronously, after all, you've got 2 threads.
When you start the thread and don't have the sleep it executes so quickly that it manages to output 5 Secondary lines within its allocated timeslice.
The Sleep call slows everything down, and because you are sleeping for a period that is reasonably large (compared to a threads timeslice) it gives the appearance of the threads running in step.
However, this is just luck. There's nothing to stop the thread scheduler deciding to suspend M0 just before it enters the lock for a period of time that allows the main thread to fully execute its loop.

C# - Method in thread is not executed

Method in thread is not executed, with thread.start();
Instead when I use thread.join() them method is executed.
Thread[] threads = new Thread[12];
int temp;
//_stopRequest = false;
for (int i = 0; i < threads.Length - 1; i++)
{
temp = i;
threads[temp] = new Thread(new ThreadStart(() => test(test1[temp],"start", temp)));
threads[temp].Start();
//threads[temp].Join();
}
Could anyone please shed light on this.
Trying to start all threads at the same time
Try to add
for(int i=0; i<threads.Length-1; i++)
{
threads[i].Join();
}
at the end of the method. Your threads will start at the same time, and you will wait for their ending. Other variant: set their IsBackground property to true. So, your program will not finish until these threads finish their work.
P.S. In your loop use "int temp = i;", if you want to work with closures. In your case, all threads closure to the same variable temp.

Erroneous behavior when using Interlocked.Decrement along with monitor.wait and monitor.pulse in a multithreaded environment

I am trying to implement a multithreaded library that would run simultaneous tasks using threadpool. Basically it will add tasks to threadpool from the collection parameter it receive and then will wait until last task that is being processed sends a pulse signal. I had success in my earlier tests but I encountered a weird issue when I wanted to test with tasks that are really short to process. Somehow either pulse signal is sent before wait command takes in place in the main thread or something else is going on that I just can't simply see regardless of my efforts for syncronization.
In order to remediate my problem I have implemented another "less desirable" solution because of the potential performance benefits I am trading off which is working well as of now, but wanted to know why my first approach doesn't work in such cases in the first place even though performance wise there are not much of a difference between the two.
To illustrate, I am adding both solutions after I simplified the processes below. Can someone help me to point what is going wrong?
Thanks in advance.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
namespace TestcodeBenchmark
{
class Program
{
static int remainingTasks = 10000000;
static Stopwatch casioF91W = new Stopwatch();
static Random rg = new Random();
static readonly object waitObject = new object();
static void Main(string[] args)
{
TestLoop(30, remainingTasks);
Console.ReadKey();
}
private static void TestLoop(int loopCount, int remainingCountResetNumber)
{
for (int i = 0; i < loopCount; i++)
{
remainingTasks = remainingCountResetNumber;
//When this method is called it eventualy stuck at Monitor.Wait line
TestInterlocked();
remainingTasks = remainingCountResetNumber;
//When this method is called it processes stuff w/o any issues.
TestManualLock();
Console.WriteLine();
}
}
private static void TestInterlocked()
{
casioF91W.Restart();
//for (int i = 0; i < remainingTasks; i++)
//{
// ThreadPool.QueueUserWorkItem(delegate { TestInterlockedDecrement(); });
//}
int toStart = remainingTasks;
//for (int i = 0; i < remainingTasks; i++)
for (int i = 0; i < toStart; i++)
{
if (!ThreadPool.QueueUserWorkItem(delegate { TestInterlockedDecrement(); }))
Console.WriteLine("Queue failed");
}
//lock waitObject to be able to call Monitor.Wait
lock (waitObject)
{
//if waitObject is locked then no worker thread should be able to send a pulse signal
//however, if pulse signal was sent before locking here remainingTasks should be
//zero so don't wait if all tasks are processed already
if (remainingTasks != 0)
{
//release the lock on waitObject and wait pulse signal from the worker thread that
//finishes last task
Monitor.Wait(waitObject);
}
}
casioF91W.Stop();
Console.Write("Interlocked:{0}ms ", casioF91W.ElapsedMilliseconds);
}
private static void TestInterlockedDecrement()
{
//process task
//TestWork();
//Once processing finishes decrement 1 from remainingTasks using Interlocked.Decrement
//to make sure it is atomic and therefore thread safe. If resulting value is zero
//send pulse signal to wake main thread.
if (Interlocked.Decrement(ref remainingTasks) == 0)
{
//Acquire a lock on waitObject to be able to send pulse signal to main thread. If main
//thread acquired the lock earlier, this will wait until main thread releases it
lock (waitObject)
{
//send a pulse signal to main thread to continue
Monitor.PulseAll(waitObject);
}
}
}
private static void TestManualLock()
{
casioF91W.Restart();
//Acquire the lock on waitObject and don't release it until all items are added and
//Wait method is called. This will ensure wait method is called in main thread
//before any worker thread can send pulse signal by requiring worker threads to
//lock waitObject to be able to modify remainingTasks
lock (waitObject)
{
for (int i = 0; i < remainingTasks; i++)
{
ThreadPool.QueueUserWorkItem(delegate { TestManualDecrement(); });
}
Monitor.Wait(waitObject);
}
casioF91W.Stop();
Console.Write("ManualLock:{0}ms ", casioF91W.ElapsedMilliseconds);
}
private static void TestManualDecrement()
{
//TestWork();
//try to acquire lock on wait object.
lock (waitObject)
{
//if lock is acquired, decrement remaining tasks by and then check
//whether resulting value is zero.
if (--remainingTasks == 0)
{
//send a pulse signal to main thread to continue
Monitor.PulseAll(waitObject);
}
}
}
private static void TestWork()
{
//Uncomment following to simulate some work.
//int i = rg.Next(100, 110);
//for (int j = 0; j < i; j++)
//{
//}
}
}
}
When you start your tasks, you loop is starting remainingTasks tasks. By the time you near 10000, however, some of the tasks have completed and decremented this number to less than 10000, so you do not start the proper number of tasks. If I modify your loop to save how many tasks should be started, the code runs successfully. (Note that you should also be checking the return value of QueueUserWorkItem.)
int toStart = remainingTasks;
for (int i = 0; i < toStart; i++)
{
if (!ThreadPool.QueueUserWorkItem(delegate { TestInterlockedDecrement(); }))
Console.WriteLine("Queue failed");
}

Categories