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.
Related
I want to create 10 threads with different names. Name should be a combination of name and id.ToString()
If I make a thread using Thread t = new Thread() then I know that I can do t.Name = name + id.ToString();, but if I there is some way to do it with the code example below I would love to know it.
string name = "Thread #";
int id = 0;
for (int i = 0; i < 10; i++)
{
new Thread(() =>
{
for (int j = 0; j <= 100; j++)
{
//Do something
}
}).Start();
}
you could do
var t = new Thread(...);
t.Name = "Thread " + i;
t.Start();
But you should probably use the thread pool instead of creating explicit threads. In this specific case where you have a loop, you should probably use a Parallel.For. In general when you want to run something on a background thread you should use Task.Run, or in some cases Dataflow. When using the task pool you should not name threads, since the threads may be reused for other things. See How can I assign a name to a task in TPL for similar concept for tasks.
Using the thread pool reduces the overhead for running things in the background, and usually also provides interfaces that are easier to use.
I just added Thread t = Thread.CurrentThread; and then I could do t.Name = $"Thread #{id}"; after.
This is what it looks like in its' entirety:
int tId = 0;
for (int i = 0; i < 10; i++)
{
new Thread(() =>
{
Thread t = Thread.CurrentThread;
tId++;
t.Name = $"Thread #{tId}";
Console.WriteLine($"{t.Name}");
}).Start();
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();
}
Want to spawn some threads and assign function to each of them later on in a loop.
Spawning the threads with
var threadList = new List<Thread>();
for (int index = 0; index < 3; index++)
{
threadList.Add(new Thread(() => { }));
}
Now in a loop want to assign function to the threads
for (int index = 0; index < names.Length; index++)
{
string tempName = names[index];
//check which thread is available
//assign a function to the first available thread
}
How do i do it?
If i am using a threadpool:
how do i get notified when all the threads are done? how do i stop the threadpool to perform any qction in queue?
Couldn't you just use ThreadPool instead?
System.Threading.ThreadPool.QueueUserWorkItem(myMethod);
This will assign your methods to an available thread which will be freed up when done.
say my main thread calls a loop which makes new threads and starts them on some other function.
for (int i = 0; i < numberOfThreads; i++)
{
Thread thread = new Thread(start);
thread.Start();
}
call_This_Function_After_All_Threads_Have_Completed_Execution();
How can i ensure that my method gets called only after all the other threads have completed execution.
You can use AutoResetEvent-s. Declare an AutoResetEvent array where all the threads can reach it.
AutoResetEvent[] events = new AutoResetEvent[numberOfThreads];
Start threads like this:
for (int i = 0; i < numberOfThreads; i++)
{
events[i] = new AutoResetEvent(false);
Thread thread = new Thread(start);
thread.Start(i);
}
WaitHandle.WaitAll(events);
call_This_Function_After_All_Threads_Have_Completed_Execution();
And finally don't forget to call the Set() method in the threads:
void start(object i)
{
//... do work
events[(int) i].Set();
}
I create my threads as
for (int i = 0; i < threadCount; i++)
{
Searcher src = new Searcher(i, this);
threads[i] = new Thread(new ThreadStart(src.getIpRange));
threads[i].Name = string.Format(i.ToString());
}
foreach (Thread t in threads)
{
t.Start();
}
with threadCount(= 100, 150, 255 etc...) but I can't learn how many threads working. on execute time.
and I want to control when all threads finishes their job. and give me a message like "All threads are dead, jobs completed..."
like backgroundWorker's RunWorkerCompleted event
Determining when all the threads are finished is simple.
for (int i = 0; i < threadCount; i++)
{
threads[i].Join();
}
Console.WriteLine("All threads are done!");
Can you elaborate on your other requirements?
You can check the ThreadState property of the Thread.
Might be better to use async methods. This gives you a WaitHandle object, and you can use WaitHandle.WaitAll to wait for all of your async methods to finish.
Here's an intro to asynchronous programming:
http://msdn.microsoft.com/en-us/library/aa719598%28v=VS.71%29.aspx
You definitely want to use the Task class for this or a higher-level concept like Parallel.ForEach. Using the Thread class directly is quite painful.
I recently wrote a blog post comparing various asynchronous approaches, listed in order from best (Task) to worst (Thread).
Here's an example using Task, demonstrating what you wanted to do:
// Start all tasks
var threads = new Task[threadCount];
for (int i = 0; i < threadCount; i++)
{
Searcher src = new Searcher(i, this);
threads[i] = Task.Factory.StartNew(src.getIpRange);
}
// How many are running right now?
var runningCount = threads.Count(x => x.Status == TaskStatus.Running);
// Register a callback when they have all completed (this does not block)
Task.Factory.ContinueWhenAll(threads, MyCallback);
Add a delegate to Searcher and pass it a callback method from your main thread that each thread will call when it finishes. As you launch each thread, add it to a Dictionary keyed by the thread's ManagedThreadId. When each thread finishes, the callback removes the thread from the Dictionary and checks to see if the count is zero.
Dictionary<int, Thread> activeThreads = new Dictionary<int, Thread>();
for (int i = 0; i < threadCount; i++)
{
Searcher src = new Searcher(i, this);
src.Done = new SearcherDoneDelegate(ThreadDone);
threads[i] = new Thread(new ThreadStart(src.getIpRange));
threads[i].Name = string.Format(i.ToString());
}
foreach (Thread t in threads)
{
lock (activeThreads)
{
activeThreads.Add(t.ManagedThreadId, t);
}
t.Start();
}
}
public void ThreadDone(int threadIdArg)
{
lock (activeThreads)
{
activeThreads.Remove(threadIdArg);
if (activeThreads.Count == 0)
{
// all done
}
}
}
public delegate void SearcherDoneDelegate(int threadIdArg);
public static object locker = new object();
public class Searcher
{
public SearcherDoneDelegate Done { get; set; }
public void getIpRange()
{
Done(Thread.CurrentThread.ManagedThreadId);
}
}
If you have more threads than you want to run at one time, put them into a Queue and peel them off as older threads finish (use the callback).
First, I have to point out that creating 100, 150, 255, etc. threads is probably not a good idea. You might be better off using the ThreadPool or Task class (if using .NET 4.0). Aside from that there are two well established methods for waiting until all threads complete.
Join the thread.
Thread.Join blocks until the target thread finishes.
for (int i = 0; i < threadCount; i++)
{
Searcher src = new Searcher(i, this);
threads[i] = new Thread(new ThreadStart(src.getIpRange));
threads[i].Name = string.Format(i.ToString());
}
foreach (Thread t in threads)
{
t.Start();
}
foreach (Thread t in threads)
{
t.Join();
}
Use a CountdownEvent.
A CountdownEvent waits until its internal count reaches zero. This method is better suited if you want to use the ThreadPool. If you are not using .NET 4.0 you can get a really simple implementation over at Joe Albahari's website.
var finished = new CountdownEvent(1);
for (int i = 0; i < threadCount; i++)
{
finished.AddCount();
Searcher src = new Searcher(i, this);
threads[i] = new Thread(
() =>
{
try
{
src.getIpRange();
}
finally
{
finished.Signal();
}
}
threads[i].Name = string.Format(i.ToString());
}
foreach (Thread t in threads)
{
t.Start();
}
finished.Signal();
finished.WaitOne();
Why can't you use critical section protected single variable to control a number of active threads? Thread function can modify this variable (having entered critical section, of course).