phoenixhawke

wondering if there's a more efficient way to do this than blocking with a while loop Seems to be a waste of cpu time...

Code Block

#region Wait for available thread
if (serviceStarted)
{

while (!fileStarted && serviceStarted)

{

#region Thread 0

if (downloads[0] == null || !(downloads[0].IsAlive) && serviceStarted)
{

downloads[0] = new Thread(DownloadFile);

downloads[0].Start(remotefile);
fileStarted = true;
}
#endregion

#region Thread 1
else if (downloads[1] == null || !(downloads[1].IsAlive) && serviceStarted)
{

downloads[1] = new Thread(DownloadFile);

downloads[1].Start(remotefile);
fileStarted = true;
}
#endregion

#region Thread 2
else if (downloads[2] == null || !(downloads[2].IsAlive) && serviceStarted)
{

downloads[2] = new Thread(DownloadFile);

downloads[2].Start(remotefile);
fileStarted = true;
}
#endregion
}
}




Note: serviceStarted is private static for the class, it is set to false when Windows calls the OnStop() command when asked to stop the service.


Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

H. Tony


you can use Mutex class, plz take a look at following msdn sample code

Code Block

static void Main()
{
// Queue up two tasks on two different threads;
// wait until all tasks are completed.
DateTime dt = DateTime.Now;
Console.WriteLine("Main thread is waiting for BOTH tasks to complete.");
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[0]);
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[1]);
WaitHandle.WaitAll(waitHandles);
// The time shown below should match the longest task.
Console.WriteLine("Both tasks are completed (time waited={0})",
(DateTime.Now - dt).TotalMilliseconds);

// Queue up two tasks on two different threads;
// wait until any tasks are completed.
dt = DateTime.Now;
Console.WriteLine();
Console.WriteLine("The main thread is waiting for either task to complete.");
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[0]);
ThreadPool.QueueUserWorkItem(new WaitCallback(DoTask), waitHandles[1]);
int index = WaitHandle.WaitAny(waitHandles);
// The time shown below should match the shortest task.
Console.WriteLine("Task {0} finished first (time waited={1}).",
index + 1, (DateTime.Now - dt).TotalMilliseconds);
}







Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

phoenixhawke

I like this threadpool thing, i was just reading up on it. Excellent.

But, ok... I need to pass a string to each of the called threads, as well as wait for all queued items to complete. How would I accomplish that




Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

H. Tony

please check this article about how to pass a string. you can use Mutex.Waitforall instead of Waitforany to handle the synchronization issue if you want to 'wait for all queued items to complete'.

phoenixhawke wrote:
I like this threadpool thing, i was just reading up on it. Excellent.

But, ok... I need to pass a string to each of the called threads, as well as wait for all queued items to complete. How would I accomplish that





Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

phoenixhawke

Ok, so i've been trying to figure this out, please bear with me as i don't have a whole lot of c# experience (or real-world programming experience in general, other than my degree).

I am trying to figure out how to queue up the downloads in the thread pool, while limiting the number of simultaneous downloads to 3.

The function downloadfile takes 1 argument in the form of a string. The example above uses a waithandle as an argument passed to the new thread, but the QueueWorkerThread method only lets you pass one argument to the thread.

1 - How do I get around that
2 - How do I limit the number of active download threads to 3 It would be nice to be able to just queue up the downloads and let the threadpool handle the rest, but from reading the documentation on ThreadPool.SetMaxThreads it seems like it would cause other problems if I used that to set the max threads to 3.

From the documentation on ThreadPool.SetMaxThreads:
Use caution when changing the maximum number of threads in the thread pool. While your code might benefit, the changes might have an adverse effect on code libraries you use.

Thanks,
Brian





Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

H. Tony

The article i posted link earlier has 3 ways of doing that. I think for beginner, you can just create a class, set string as a member variable, pass function within that class intsance to your new thread.

for the limitation, you can use a lock, main program locks/checks a counter, if it's less than 3, increment counter, create new thread to download, otherwise wait. when thread finishes processing, it locks counter and decrease it by 1.

you dont really have to check if the thread has finished or not.

there are other more efficient ways, this is a simple start, IMHO

phoenixhawke wrote:
Ok, so i've been trying to figure this out, please bear with me as i don't have a whole lot of c# experience (or real-world programming experience in general, other than my degree).

I am trying to figure out how to queue up the downloads in the thread pool, while limiting the number of simultaneous downloads to 3.

The function downloadfile takes 1 argument in the form of a string. The example above uses a waithandle as an argument passed to the new thread, but the QueueWorkerThread method only lets you pass one argument to the thread.

1 - How do I get around that
2 - How do I limit the number of active download threads to 3 It would be nice to be able to just queue up the downloads and let the threadpool handle the rest, but from reading the documentation on ThreadPool.SetMaxThreads it seems like it would cause other problems if I used that to set the max threads to 3.

From the documentation on ThreadPool.SetMaxThreads:
Use caution when changing the maximum number of threads in the thread pool. While your code might benefit, the changes might have an adverse effect on code libraries you use.

Thanks,
Brian






Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

phoenixhawke

What I'd like to be able to do would be to call some kind of wait/sleep function when I reach the max threads that gets triggered to resume as soon as a thread becomes available, in order to minimize the number of operations being sent to the processor




Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

H. Tony

sure, the main thread can simply call System.Threading.Thread.Sleep(100); in the while loop so that the CPU utilization will be low.

phoenixhawke wrote:
What I'd like to be able to do would be to call some kind of wait/sleep function when I reach the max threads that gets triggered to resume as soon as a thread becomes available, in order to minimize the number of operations being sent to the processor





Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

phoenixhawke

So there's really no way to just have some kind of semaphore system where the worker thread sends a message back to the main thread saying "Hey, I'm available, wake up and start another download"




Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

H. Tony

of course there are ways, the earlier code I posted about Mutex is one.

btw, considering how fast today's computers are, a few cpu cycles on the check per 100millionsecond is really pretty efficient. as long as you call sleep in the while loop, it shouldn't be big impact on your CPU utilization

phoenixhawke wrote:
So there's really no way to just have some kind of semaphore system where the worker thread sends a message back to the main thread saying "Hey, I'm available, wake up and start another download"





Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

phoenixhawke

Ok, so i figured out how to use the ManualResetEvent to accomplish the semaphore system, using an array of three of them and Thead.CurrentThread.GetHashCode() to identify which thread is which to the main thread. The very last thing my download threads do now (in a finally block) is call semaphore[index].Set().

The main thread is sitting there in a WaitHandle.WaitAny(semaphore) per your earlier suggestion, and creates a hash table containing the local semaphore array index and the hash code of the thread it creates so that the thread can reset the corresponding semaphore. This seemed ideal because I could use the hash code as the key in the hash table.

Code Block

#region Wait for available thread
if (serviceStarted)
{
WaitIndex = WaitHandle.WaitAny(semaphore);
lock (semaphore[WaitIndex])
{
semaphore[WaitIndex].Reset();
}
if(downloads[WaitIndex] != null)
downloads[WaitIndex].Join(); //Make sure thread actually returns before starting new thread
downloads[WaitIndex] = new Thread(DownloadFile);
downloads[WaitIndex].IsBackground = true;
downloads[WaitIndex].Start(remotefile);
lock (ThreadIdtoIndex)
{
ThreadIdtoIndex.Add(downloads[WaitIndex].GetHashCode(), WaitIndex);
}
}
#endregion




Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

H. Tony

it sounds very good.

phoenixhawke wrote:
Ok, so i figured out how to use the ManualResetEvent to accomplish the semaphore system, using an array of three of them and Thead.CurrentThread.GetHashCode() to identify which thread is which to the main thread. The very last thing my download threads do now (in a finally block) is call semaphore[index].Set().

The main thread is sitting there in a WaitHandle.WaitAny(semaphore) per your earlier suggestion, and creates a hash table containing the local semaphore array index and the hash code of the thread it creates so that the thread can reset the corresponding semaphore. This seemed ideal because I could use the hash code as the key in the hash table.

Code Block

#region Wait for available thread
if (serviceStarted)
{
WaitIndex = WaitHandle.WaitAny(semaphore);
lock (semaphore[WaitIndex])
{
semaphore[WaitIndex].Reset();
}
if(downloads[WaitIndex] != null)
downloads[WaitIndex].Join(); //Make sure thread actually returns before starting new thread
downloads[WaitIndex] = new Thread(DownloadFile);
downloads[WaitIndex].IsBackground = true;
downloads[WaitIndex].Start(remotefile);
lock (ThreadIdtoIndex)
{
ThreadIdtoIndex.Add(downloads[WaitIndex].GetHashCode(), WaitIndex);
}
}
#endregion





Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

phoenixhawke

Thanks for the help... this threading stuff is hard to wrap your brain around Smile




Re: Visual C# General Is there an efficient way to wait for any one of a group of threads to exit?

ben.biddington

Also, this article is good: http://msdn.microsoft.com/msdnmag/issues/07/05/CLRInsideOut/