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.
Related
This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed 3 months ago.
Been working on a program recently and have a question about a problem I ran into. I've solved it, but don't know why it's happening:
for(int i = 0; i<10; i++)
{
Thread t = new Thread (() => {(does stuff, uses "i")});
}
Essentially I have 10 known processes I want to run on separate threads. In the thread, the value of the incrementor "i" is used to assign an object to a position in another array (I use locking). Now if I run it as is, I get an out of bounds error and when I debug with code breaks, I find that on that last loop i is equal to 10, when the last value should be 9. When this code isn't threaded, it works perfectly fine.
I decided to try and assign the incrementer to a local variable inside the thread:
for(int i = 0; i<10; i++)
{
Thread t = new Thread (() =>
{
localI=i;
(does stuff, uses "localI")
});
}
This had the same issue. I did more reading online and tried a different ordering of it:
for(int i = 0; i<10; i++)
{
localI=i;
Thread t = new Thread (() =>
{
(does stuff, uses "localI")
});
}
And this code works. I can't at all figure out why this works, but the second example didn't. Could anyone help me figure it out?
Thanks
Effectively there are 11 threads, your main thread running the for loop and the threads you spawn.
By the time your 10 new threads run the main loop might well be finished and the value of i will be 10. If you then use this to index an array you will get the out of bounds error.
Your third example assigns i to the localI var, this will keep its value and the individual threads will use that saved value of localI.
It`s simple.
The i variable is run on main thread and for loop reaches 10 value even before the child thread initiates. So, you can add a local variable outside of child threads to get fixed value on every loop.
And, for loop set 10 on i variable, but not run loop, because gets false on checks.
Simple test:
class Program
{
static void Main(string[] args)
{
Test c = new Test();
Console.WriteLine("NonLocal:");
Console.WriteLine(string.Join(",", c.NonLocal));
Console.WriteLine();
Console.WriteLine("Local:");
Console.WriteLine(string.Join(",", c.Local));
Console.ReadLine();
}
}
class Test
{
public object locker;
public List<object> NonLocal; // use List<> for dynamic array
public object[] Local;
public Test()
{
this.locker = new object();
this.NonLocal = new List<object>();
this.Local = new object[10];
// child thread pool
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10; i++)
{
int localI = i;
Thread t = new Thread(() =>
{
lock (locker)
{
// adding to result only index
// to see value on i variable on this point
this.NonLocal.Add(i);
// using a fixed local variable
this.Local[localI] = localI;
}
});
threads.Add(t);
t.Start();
}
// wait until threads end
while (true)
{
if (!threads.Any(x => x.IsAlive)) break;
}
}
}
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 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.
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.
I have a main thread which is controlling a windows form, upon pressing a button two threads are executed. One is used for recording information, the other is used for reading it. The idea behind putting these in threads is to enable the user to interact with the interface while they are executing.
Here is the creating of the two threads;
Thread recordThread = new Thread(() => RecordData(data));
recordThread.Name = "record";
recordThread.Start();
Thread readThread = new Thread(() => ReadData(data));
readThread.Name = "read";
readThread.Start();
The data is simply a Data-object that stores the data that is recorded during the recording.
The problem that I am facing is that the first thread is executed fine, the second refuses to run until the first one completes. Putting a breakpoint in the second threads function, ReadData lets me know that it is only called after the first thread is done with all of its recording.
I have been trying to solve this for a few hours now and I can't get my head around why it would do this. Adding a;
while(readThread.IsAlive) { }
right after the start will halt the execution of anything after that, and it's state is Running. But it will not go to the given method.
Any ideas?
Edit:
The two functions that are called upon by the threads are;
private void RecordData(Data d)
{
int i = 0;
while (i < time * freq)
{
double[] data = daq.Read();
d.AddData(data);
i++;
}
}
private void ReadData(Data d)
{
UpdateLabelDelegate updateData =
new UpdateLabelDelegate(UpdateLabel);
int i = 0;
while (i < time * freq)
{
double[] data = d.ReadLastData();
this.Invoke(updateData, new object[] { data });
i++;
}
}
The data object has locking in both the functions that are called upon; ReadLastData and Read.
Here are the methods in the Data object.
public void AddData(double[] data)
{
lock (this)
{
int i = 0;
foreach (double d in data)
{
movementData[i].Add(d);
i++;
}
}
}
public double[] ReadLastData()
{
double[] data = new double[channels];
lock (this)
{
int i = 0;
foreach (List<double> list in movementData)
{
data[i] = list[list.Count - 1];
}
}
return data;
}
Looks like you have a race condition between your reading/writing. In your first thread you lock down the object whilst you add data to it and in the second thread you attempt to get an exclusive lock on it to start reading. However, the problem is the first thread is executing so fast that the second thread never really gets a chance to acquire the lock.
The solution to this problem really depends on what sort of behaviour you are after here. If you expect after every write you get a consecutive read then what you need to do is control the execution between the reading/writing operations e.g.
static AutoResetEvent canWrite = new AutoResetEvent(true); // default to true so the first write happens
static AutoResetEvent canRead = new AutoResetEvent(false);
...
private void RecordData(Data d)
{
int i = 0;
while (i < time * freq)
{
double[] data = daq.Read();
canWrite.WaitOne(); // wait for the second thread to finish reading
d.AddData(data);
canRead.Set(); // let the second thread know we have finished writing
i++;
}
}
private void ReadData(Data d)
{
UpdateLabelDelegate updateData =
new UpdateLabelDelegate(UpdateLabel);
int i = 0;
while (i < time * freq)
{
canRead.WaitOne(); // wait for the first thread to finish writing
double[] data = d.ReadLastData();
canWrite.Set(); // let the first thread know we have finished reading
this.Invoke(updateData, new object[] { data });
i++;
}
}
Could you try adding a Sleep inside RecordData?
Maybe it's just your (mono cpu??) windows operating system that doesn't let the second thread get its hand on cpu resources.
Don't do this:
lock (this)
Do something like this instead:
private object oLock = new object();
[...]
lock (this.oLock)
EDIT:
Could you try calls like this:
Thread recordThread = new Thread((o) => RecordData((Data)o));
recordThread.Name = "record";
recordThread.Start(data);