Dynamically assign function to threads - c#

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.

Related

Can I name each thread in this example?

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();

How do i ensure statement gets executed after all the threads have completed execution

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();
}

Multi-threads not terminating after for loop executes

I have n number of threads which run a method routine. With each thread running the search method, and searching for items in a given range, the items are retrieved from a web server. But I believe that they keep on running, even when the range is exhausted. I am using a for loop to determine when the thread should stop searching, but that is not working out. This is what I have:
In method Start() I compute a certain range, and that range is given to a thread, which is to search in this given range.
public void Start()
{
this.totalRangePerThread = ((this.endRange - this.startRange) / this.subWorkerThreads.Length);
for (int i = 0; i < this.subWorkerThreads.Length; ++i)
{
var copy = startRange;
this.subWorkerThreads[i] = new Thread(() => searchItem(copy, this.totalRangePerThread));
this.startRange = this.startRange + this.totalRangePerThread;
}
for (int threadIndex = 0; threadIndex < this.subWorkerThreads.Length; ++threadIndex)
this.subWorkerThreads[threadIndex].Start();
}
This is my SearchItem() method:
public void searchItem(int start, int pagesToSearchPerThread)
{
for (int count = 0; count < pagesToSearchPerThread; ++count)
{
start++;
for (int activeListCount = 0; activeListCount < this.activeListItems.Count; ++activeListCount)
{
//further method calls here to webservers..
}
}
}
I know about using some shared sentinel to determine when to stop a thread, but I fail to comprehend how to apply it here? How should I be handling this scenario, such that a thread aborts gracefully, when its task is completed...

What's the proper way to wait on a Semaphore?

I thought that the following code would let all the 10 threads run, two at a time, and then print "done" after Release() is called 10 times. But that's not what happened:
int count = 0;
Semaphore s = new Semaphore(2, 2);
for (int x = 0; x < 10; x++)
{
Thread t = new Thread(new ThreadStart(delegate()
{
s.WaitOne();
Thread.Sleep(1000);
Interlocked.Increment(ref count);
s.Release();
}));
t.Start(x);
}
WaitHandle.WaitAll(new WaitHandle[] { s });
Console.WriteLine("done: {0}", count);
output:
done: 6
If the only way to implement the functionality I'm looking for is to pass an EventWaitHandle to each thread and then do a WaitAll() on an array of those EventWaitHandles, then what's the meaning of doing a WaitAll() on an array of only a semaphore? In other words, when does the waiting thread unblock?
WaitHandle.WaitAll just waits until all the handlers are in signalled state.
So when you call WaitHandle.WaitAll on one WaitHandle it works the same as you call s.WaitOne()
You can use, for example, the following code to wait for all the started threads, but allow two threads to run in parallel:
int count = 0;
Semaphore s = new Semaphore(2, 2);
AutoResetEvent[] waitHandles = new AutoResetEvent[10];
for (int x = 0; x < 10; x++)
waitHandles[x] = new AutoResetEvent(false);
for (int x = 0; x < 10; x++)
{
Thread t = new Thread(threadNumber =>
{
s.WaitOne();
Thread.Sleep(1000);
Interlocked.Increment(ref count);
waitHandles[(int)threadNumber].Set();
s.Release();
});
t.Start(x);
}
WaitHandle.WaitAll(waitHandles);
Console.WriteLine("done: {0}", count);
WaitHandle.WaitAll(new WaitHandle[] { s }); waits just like s.WaitOne();. It enters at the first opportunity. You seem to expect this call to wait for all other semaphore operations but there is no way the operating system can tell the difference. This command might well be the first that is granted access to the semaphore.
I think what you need is the Barrier class. It is made for fork-join-style parallelism.

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.

Categories

Resources