Thread start passed integer changes itself beyond what it should be [duplicate] - c#

This question already has an answer here:
Thread alters passed Int, if start() is called separately
(1 answer)
Closed 7 years ago.
I have no idea what is going on in this. I'm trying to test thread safety of a class by spawning 100 threads to access it constantly, but it seems my anonymous method parameters are changing themselves to values they should never be and I'm confused as to why. As I have no idea what's going on, I'll just post all the functions involved in testing. Somehow I'm ending up with "Thread 98" getting the parameter "num = 100"... That shouldn't be possible and I have no idea what kind of hokey pokey is going on that is changing the integer. (in method "ThreadWriting(int num)" you'll see the point where I check for "num" to equal 100, where I put a break point to catch the offending thread in the act, and it breaks every time. Otherwise it throws an "IndexOutofRangeException" on the array "counts". I'm just trying to see if my threads are generally getting equal access to the class they're all trying to use at once.
public delegate void TempDel();
public TempDel InvokeTest;
public void TRTest3(Form1 sender)
{
InvokeTest = new TempDel(UpdateInvoke);
Thread t = new Thread(() => ConsoleUpdateTest(sender));
t.IsBackground = true;
t.Start();
POConsole.Instance.MaxLines = 20;
for(int i = 0; i < 100; i++)
{
Thread t2 = new Thread(() => ThreadWriting(i));
t2.IsBackground = true;
t2.Name = String.Format("Thread {0}", i);
t2.Start();
}
}
public ulong[] counts = new ulong[100];
public void ThreadWriting(int num)
{
if(num == 100)
{
bool stop = true;
}
while (true)
{
POConsole.Instance.WriteLine("Hello from Thread " + num);
counts[num]++;
}
}
public void ConsoleUpdateTest(Form1 sender)
{
while(true)
{
sender.Invoke(InvokeTest);
Thread.Sleep(5);
}
}
public void UpdateInvoke()
{
QuickTestBox.Text = POConsole.Instance.FullFeed;
}
All my threads are named, as you can see, and none of them receives the name "Thread 100" so I have no idea how one of the other threads could get passed a parameter of 100 or the parameter could be corrupted in some way.
Apparently my thread-safety checking isn't thread safe in some way?

This is a simple closure issue, you should not be using the for loop counter as a threading parameter issue, issue happens out here, for loop and thread execution do not run at same speed, so value of i can change for multiple threads:
for(int i = 0; i < 100; i++)
{
Thread t2 = new Thread(() => ThreadWriting(i));
t2.IsBackground = true;
t2.Name = String.Format("Thread {0}", i);
t2.Start();
}
Use following modification, create a local variable from loop counter
for(int i = 0; i < 100; i++)
{
int j = i;
Thread t2 = new Thread(() => ThreadWriting(j));
t2.IsBackground = true;
t2.Name = String.Format("Thread {0}", j);
t2.Start();
}

Related

C# Threading inside for loop [duplicate]

This question already has answers here:
Waiting for all threads to complete, with a timeout
(10 answers)
Closed 6 years ago.
I want the for loop to complete before I print the result, in:
for (int i = 0; i < 5; i++)
{
(new System.Threading.Thread(() =>
{
if (TimeTakingMethod())
{
++nResult;
}
})).Start();
}
Console.WriteLine("Count = " + nResult);
but Console.WriteLine will not wait for those threads to finish because printing is done on the main thread.
If I change it to:
System.Threading.Thread t = new System.Threading.Thread(() =>
{
for (int i = 0; i < 5; i++)
{
(new System.Threading.Thread(() =>
{
if (TimeTakingMethod())
{
++nResult;
}
})).Start();
}
});
t.Start();
t.Join();
Console.WriteLine("Count = " + nResult);
it will still not solve the problem because the nested threads will not be waited for.
Any simple solution to this? Thanks for going through this.
You should store the created threads to control them, I used a List.
int nResult = 0;
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 5; i++)
{
Thread thread = new System.Threading.Thread(() =>
{
if (TimeTakingMethod())
{
++nResult;
}
});
thread.Start();
threads.Add(thread);
}
foreach (Thread thread in threads)
thread.Join();
Console.WriteLine("Count = " + nResult);
An example of how you could do this:
int result = 0;
Task.WaitAll(Enumerable.Range(0, 5)
.Select(index => Task.Factory.StartNew(() =>
{
// Do thread things...
Interlocked.Increment(ref result);
})).ToArray());
Console.WriteLine(result);
The two important things to note are Task.WaitAll which will cause the program to wait for all tasks to complete before moving on to the WriteLine call.
Also Interlocked.Increment will allow you to safely increment result from any thread.

Multithreading issue updating the value

I have difficulty understanding why the multithreading fails to update values before the thread completes. Does the separate thread have its own copy of the references or values?
If not, to my understanding the code below should work properly when MyMethod is called, but often it does not create instances of some MyType objects in the array before the thread.IsAlive becomes false:
class MyClass
{
static MyType[] obj = new MyType[Environment.ProcessorCount - 1];
void MyMethod()
{
Thread[] threads = new Thread[Environment.ProcessorCount - 1];
for (int i = 0; i < Environment.ProcessorCount - 1; i++)
{
threads[i] = new Thread(() => FillObjects(i));
threads[i].Priority = ThreadPriority.AboveNormal;
threads[i].Start();
}
while (threads[i].Any(c => c.IsAlive))
{
Thread.Sleep(50);
}
}
void FillObjects(int i)
{
obj[i] = new MyType();
//perform actions with obj[i] to fill it with necessary values
}
}
You need to assign the value of the loop variable to a local variable. Otherwise it's possible that the first execution of FillObjects(i) is executed after i was incremented so FillObjects(0) is never called and therefore obj[0] is never assigned.
void MyMethod()
{
Thread[] threads = new Thread[Environment.ProcessorCount - 1];
for (int i = 0; i < Environment.ProcessorCount - 1; i++)
{
int local = i;
threads[i] = new Thread(() => FillObjects(local));
threads[i].Priority = ThreadPriority.AboveNormal;
threads[i].Start();
}
while (threads.Any(c => c.IsAlive))
{
Thread.Sleep(50);
}
}
On a multi processor machine (which you must have) results written to a memory location in one thread may not be visible in another thread due to caching. Use Thread.VolatileRead and Thread.VolatileWrite read in order to read and write "through" the cache.
Cf. the chapter on threading in c# 3.0 in a Nutshell for an explanation. (Look for the question "Is it possible for the Wait method to write "False"?". That example is basically your case.)

Threadpool issue Using C#

I'm working on my university project. One of main requirement is to use multithreading (user can choose threads numbers).
I'm new in C# and based on internet research. I choose ThreadPool.
I spent a lot of time observing how the threads act using parallel watch in VS and i have no idea how this thing works. For example threadNumber = 10 but parallel watch shows only 4 activated threads.
Here is my code:
public void calculateBeta()
{
var finished = new CountdownEvent(1);
for (int i = 0; i < threadNumber; i++)
{
finished.AddCount();
ThreadPool.QueueUserWorkItem(
(state) =>
{
try
{
doSth();
}
finally
{
finished.Signal();
}
});
}
finished.Signal();
finished.Wait();
}
What am I doing wrong? I tried to test this code with many different values of threads number and it didn't work as i looked for.
EDIT:
private void myTask(object index)
{
int z = (int)index;
double[] result = countBeta(createTableB(z), createTableDiagonalA(z));
int counter = 0;
if ((rest != 0) && (z == threadNumber - 1))
{
for (int j = z * numbersInRow; j < (z + 1) * numbersInRow + rest; j++)
{
N[j] = result[counter];
counter++;
}
}
else
{
for (int j = z * numbersInRow; j < (z + 1) * numbersInRow; j++)
{
N[j] = result[counter];
counter++;
}
}
threads[z] = true;
}
public void calculateBeta()
{
N = new double[num];
setThreadNumber(2);
checkThreadNumber();
setNumberInRow();
setRest();
threads = new bool[threadNumber];
for (int i = 0; i < threadNumber; i++)
{
Thread thread = new Thread(this.myTask);
thread.IsBackground = true;
thread.Start(i);
}
while (!checkThreads())
{
}
}
private bool checkThread()
{
bool result = true;
for (int i = 0; i < threads.Length; i++)
{
if (!threads[i])
result = false;
}
return result;
}
static void Main(string[] args)
{
Jacobi jacobi = new Jacobi();
Console.WriteLine("Metoda Jacobiego");
Console.WriteLine("Rozwiazywanie ukladu n-rownan z n-niewiadomymi Ax=b");
jacobi.getNum();
jacobi.getA();
jacobi.getB();
jacobi.calculateBeta();
jacobi.calculateM();
jacobi.calculateX();
jacobi.countNorms();
Console.ReadLine();
}
I need results from calculateBeta to further calculations. Sometimes threads are not finished yet but the program moves forward without data that need to be provided by threads. I'm using bool variable now but this solution is not an elegant way to deal with it(Creating bool table, checking if all thread are fnished) How can i manage with that in a different way?
This is because you're using ThreadPool to manage your threads. It will create a certain number of threads based on many factors. You can tweak some of the settings but by and large when you commit to using ThreadPool to managing your threads you commit to a black box. Check out GetMaxThreads and GetMinThreads and their setter counterparts for some of your options.
Check out this ThreadPool Architecture article on MSDN. It gives good background to the hows and whys of the class. But in the introductory paragraph you will see this sentence, which is key to your conundrum:
The thread pool is primarily used to reduce the number of application
threads and provide management of the worker threads.
If you want to have the kind of control where you launch 10 threads in quick succession you should avoid ThreadPool and just manage the threads yourself. Here is a simple, absolutely minimal example of launching ten threads and also passing different data to each, in this case an index:
void ButtonClickHandlerOrSomeOtherMethod()
{
for (int i=1; i<=10; i++) // using a 1-based index
{
new Thread(ThreadTask).Start(i);
}
}
void ThreadTask(object i)
{
Console.WriteLine("Thread " + i + " ID: " + Thread.CurrentThread.ManagedThreadId);
}
And some sample output:
Thread 1 ID: 19
Thread 2 ID: 34
Thread 3 ID: 26
Thread 4 ID: 5
Thread 5 ID: 36
Thread 6 ID: 18
Thread 7 ID: 9
Thread 8 ID: 38
Thread 9 ID: 39
Thread 10 ID: 40
Follow-up code demonstrating synching with threads and "waiting" until they are all finished:
void ButtonClickHandlerOrSomeOtherMethod()
{
// need a collection of threads to call Join after Start(s)
var threads = new List<Thread>();
// create threads, add to List and start them
for (int i=1; i<=10; i++) {
var thread = new Thread(ThreadTask);
threads.Add(thread);
// a background thread will allow main app to exit even
// if the thread is still running
thread.IsBackground = true;
thread.Start(i);
}
// call Join on each thread which makes this thread wait on
// all 10 other threads
foreach (var thread in threads)
thread.Join();
// this message will not show until all threads are finished
Console.WriteLine("All threads finished.");
}
void ThreadTask(object i)
{
Console.WriteLine("Thread " + i + " ID: " + Thread.CurrentThread.ManagedThreadId);
// introducing some randomness to how long a task "works on something"
Thread.Sleep(100 * new Random().Next(0, 10));
Console.WriteLine("Thread " + i + " finished.");
}
The whole design of the thread pool is that it doesn't have to create a new actual thread every time a new item is queued up. If the pool notices that it has items pending in the queue for an extended period of time it will eventually start spinning up new threads, over time. If you're continually saturating the thread pool with operations, you'll see the number of actual threads rise. It will also only add new threads up to a limit; based on what it feels is going to have the best throughput. For example, it will avoid creating a lot more threads than cores assuming all of the threads are actively running CPU bound work.
The idea of using the thread pool is if you don't care how many actual threads there are, but rather just want to have efficient throughput of the operations that you have, allowing the framework lots of freedom on how to best optimize that work. If you have very specific requirements as to how many threads you have, you'll need to create threads manually rather than using a pool.
// Array of threads launched.
// This array is useful to trace threads status.
Thread[] threads;
private void myTask(object index)
{
Console.Write("myTask {0} started\n", index);
Console.Write("myTask {0} finisced\n", index);
}
public void calculateBeta(UInt16 threadNumber)
{
// Allocate a new array with size of requested number of threads
threads = new Thread[threadNumber];
// For each thread
for (int i = 0; i < threadNumber; i++)
{
// Thread creation
threads[i] = new Thread(this.myTask);
// IsBackground set to true grants that the allication can be "killed" without wait for all threads termination
// This is useful in debug to be sure that an error in task doesn't freeze the app.
// Leave it to false in release
#if DEBUG
threads[i].IsBackground = true;
#endif
// Start the thread
threads[i].Start(i);
}
// Waits until all threads complete.
while (!checkThreads());
}
private bool checkThreads()
{
bool result = true;
for (int i = 0; i < threads.Length; i++)
{
// If the thread wasn't disposed
if (threads[i] != null)
{
// Check if the thead is alive (means is working)
if (threads[i].IsAlive == true)
{
result = false;
}
else // The thread is not working
{
// Dispose the thread
threads[i].Join();
// Set pointer to null to signal that the task was
threads[i] = null;
}
}
}
return result;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Console.Write("Starting tasks!!\n");
calculateBeta(10);
Console.Write("All tasks finished!!\n");
}

When All Threads Are Complete

This is my first real attempt at using multithreading, I want to know how I can tell when all of my tasks groups are done running:
for (int i = 0; i < taskGroups.Count(); i++) {
ThreadStart t = delegate { RunThread(taskGroups[i]); };
new Thread(t).Start();
}
if(allThreadsComplete){ //???
}
Any help would be much appreciated
Addendum:
ThreadStart[] threads = new ThreadStart[taskGroups.Count()];
for (int i = 0; i < taskGroups.Count(); i++) {
threads[i] = new ThreadStart[]
threads[i] = delegate { RunThread(taskGroups[i]); };
new Thread(t).Start();
}
bool threadsComplete = false;
while(!threadsComplete){
for(int i=0;i<taskGroups.Count();i++){
if(threads[i].State == complete)
threadsComplete = true;
}
}
You need to store all your threads, and then call Thread.Join().
Something like this:
List<Thread> threads = new List<Thread>();
for (int i = 0; i < taskGroups.Count(); i++) {
int temp = i; //This fixes the issue with i being shared
Thread thread = new Thread(() => RunThread(taskGroups[temp]));
threads.Add(thread);
thread.Start();
}
foreach (var thread in threads) {
thread.Join();
}
If you're using 3.5 then you can write your own CountdownEvent, if you're using 4.0 then you can use the built in CountdownEvent to do something like this:
CountdownEvent = new CountdownEvent(taskGroups.Count());
for (int i = 0; i < taskGroups.Count(); i++)
{
int item = i; // copy i locally
ThreadStart t = delegate
{
RunThread(taskGroups[item]);
latch.Signal();
};
new Thread(t).Start();
}
latch.Wait();
The latch.Wait() will cause your code to block until the threads have all finished. Furthermore, you might want to change the way you start your thread a bit:
CountdownEvent = new CountdownEvent(taskGroups.Count());
for (int i = 0; i < taskGroups.Count(); i++)
{
int item = i; // copy i locally
Thread t = new Thread(()=>
{
RunThread(taskGroups[item]);
latch.Signal();
});
t.IsBackground = true;
t.Start();
}
latch.Wait();
Note that I'm setting the thread to background: this your application from hanging when exit and not all threads have finished (i.e. prevents ghost or daemon threads).
You can use Thread.Join to make sure that each individual thread has finished running.
You can add public static integer field to the main thread, in each child thread increase it by one when it's completed then in the main thread wait (in a loop) until that variable is equal to the taskGroups.Count().
First of all consider switching to the new asynchronous pattern using Task.
Anyway if you want to wait for all your threads you can call Thread.Join:
var threads = new List<Thread>();
for (int i = 0; i < taskGroups.Count(); i++) {
ThreadStart t = delegate { RunThread(taskGroups[i]); };
var thread = new Thread(t);
threads.Add(thread);
thread.Start();
}
threads.ForEach(a => a.Join());
Remember that you can also pass a timeout parameter that will wait until the thread finishes only if it doesn't takes more than the time you passed in.
You can check the ThreadState property of each Thread object.

Race condition for thread startup

A similar question was asked here, but the answers generally all seem to relate to the lambda notation. I get a similar result without the lambda so I thought I'd ask for some clarification:
Say I have something like this:
for (int i = 0; i < 5; i++)
(new Thread(new ThreadStart(delegate()
{
Console.WriteLine("Thread " + i);
}))).Start();
One would expect the following output:
Thread 0
Thread 1
Thread 2
Thread 3
Thread 4
Now I realise that the threads aren't started in any particular order, so let's just assume that the above lines can come out in any order.
But that is not what happens.
What instead happens:
Thread 3
Thread 4
Thread 4
Thread 4
Thread 4
or something similar, which leads me to believe that rather than passing the value if i, it is passing the reference. (Which is weird, since an int is a value type).
Doing something like this:
for (int i = 0; i < 5; i++)
(new Thread(new ThreadStart(delegate()
{
int j = i;
Console.WriteLine("Thread " + j);
}))).Start();
does not help either, even though we have made a copy of i. I am assuming the reason is that it hasn't made a copy of i in time.
Doing something like this:
for (int i = 0; i < 5; i++)
{
(new Thread(new ThreadStart(delegate()
{
Console.WriteLine("Thread " + i);
}))).Start();
Thread.Sleep(50);
}
seems to fix the problem, however it is extremely undesirable as we're wasting 50ms on each iteration, not to mention the fact that if the computer is heavily loaded then maybe 50ms may not be enough.
Here is a sample with my current, specific problem:
Thread t = new Thread(new ThreadStart(delgate()
{
threadLogic(param1, param2, param3, param4);
}));
t.Start();
param1 = param2 = param3 = param4 = null;
with:
void threadLogic(object param1, object param2, object param3, object param4)
{
// Do some stuff here...
}
I want threadLogic() to run in its own thread, however the above code gives a null reference exception. I assume this is because the values are set to null before the thread has had a chance to start.
Again, putting a Thread.Sleep(100) works, but it is an awful solution from every aspect.
What do you guys recommend for this particular type of race condition?
You need to introduce a temporary:
for (int i = 0; i < 5; i++)
{
int temp = i; // Add this
(new Thread(new ThreadStart(delegate()
{
Console.WriteLine("Thread " + temp);
}))).Start();
}
The problem is in how delegates close around the outer variable (i in your code, temp in mine). The scope is wrong (outside the for loop), so by the time the thread starts, i has already been incremented most if not all of the way.
For your second example, you need to do the same thing. Just make temporaries:
var temp1 = param1;
var temp2 = param2;
var temp3 = param3;
var temp4 = param4;
Thread t = new Thread(new ThreadStart(delgate()
{
threadLogic(temp1, temp2, temp3, temp4);
}));
t.Start();
// This is now safe, since the closure above is over "temp*"
param1 = param2 = param3 = param4 = null;
Your issue is the same; it's not the lambda syntax itself, it's the fact that you're closing over a local variable in an anonymous method (the delegate syntax you're using was the first iteration of anonymous methods, which made its debut in .NET 2.0).
If you want to do this, you'll have you use a workaround:
for (int i = 0; i < 5; i++)
{
int j = i;
(new Thread(new ThreadStart(delegate()
{
Console.WriteLine("Thread " + j);
}))).Start();
}
Note that this is similar to what you tried (copying), but it needs to be outside of the closure and inside the loop. Copying it within the anonymous function (like in your example) doesn't help.

Categories

Resources