Make multithreading do only X threads at a time.
(Thursday, December 23, 2004)
Found the following interesting discussion in the Newsgroups:
Make multithreading do only X threads at a time. by:Manuel
| I have a long function that needs to be done 1000 times. I'm multithreading it, but I don't want to load them up all at once, instead load them 10 at a time.
So far the only way I can get it to work is by creating a dummy form with a timer. On the timer function I test if the number of threads are less than 10 then run the remaining ones. This is working fine, but I would like to know how to do it without the form.
This is the code I'm trying to use to accomplish the feat without the form:
Module mdlAny() Public Sub Main() Do FunctionThatCalls10Threads() PauseThisThing() 'Replace this with 'either of the bottom functions Loop End Sub
Private Sub PauseThisThingThatWorks() 'It works with this code: 'On the Timer event, I call 'the FunctionThatChecksTheNumberOfThreads() 'to see if I can close the form. '(and hence continue with the program)
Dim wf As WaitForm = New WaitForm wf.ShowDialog() End Sub
Private Sub PauseThisThingThatDOESNOTWork() 'It doesn't work with this code for waiting
Dim RetValue as Boolean Do System.Threading.Thread.CurrentThread.Sleep(1000) RetValue = FunctionThatChecksTheNumberOfThreads() Loop Until RetValue End Sub End Module
................................................................. Posted via TITANnews - Uncensored Newsgroups Access >>>> at http://www.TitanNews.com <<<< -=Every Newsgroup - Anonymous, UNCENSORED, BROADBAND Downloads=-
| | | Reply: by:Tom Shelton
| | |
' Dummy code, in a fictious Console application Option Strict On Option Explicit On
Imports System Imports System.Threading
Module modMain Private Const MAX_THREADS As Integer = 9 Private threads(MAX_THREADS) As Thread
' just so we can get the system thread handle :) Private Declare Function GetCurrentThreadId Lib "kernel32" () As IntPtr
Public Sub Main() Dim rnd As New Random
For i As Integer = 0 To MAX_THREADS threads(i) = New Thread(AddressOf Run)
' randomize the wait... Thread.Sleep(rnd.Next(100, 1000))
threads(i).Start() Next
Console.ReadLine()
For i As Integer = 0 To MAX_THREADS threads(i).Abort() Next
Console.ReadLine() End Sub
Private Sub Run() Dim i As Integer = 0 Dim id As Integer = GetCurrentThreadId().ToInt32()
Try Do i += 1 Console.WriteLine("ThreadId {0}: i={1}", _ id, i) Thread.Sleep(1000) Loop Catch ex As ThreadAbortException Console.WriteLine("ThreadID {0} Aborted!", id) End Try End Sub End Module
I'm not sure if this is what you wanted... But maybe it will help you :) -- Tom Shelton [MVP]
| | | Reply: by:Manuel
| | | Tom Shelton wrote:
> > I'm not sure if this is what you wanted... But maybe it will help you :)
Not quite. What you are doing is starting the threads every X amount of time, where X is a random number.
I want to be able to run 10 threads and then wait until less than 10 are finished and load 10 more, rinse and repeat...
Thanks
................................................................. Posted via TITANnews - Uncensored Newsgroups Access >>>> at http://www.TitanNews.com <<<< -=Every Newsgroup - Anonymous, UNCENSORED, BROADBAND Downloads=-
| | | Reply: by:Jay B. Harlow [MVP - Outlook]
| | | Manuel, In addition to my other comments.
The reason I suggested a thread pool (either the built in one, or roll your own).
Is that starting & stopping 1000 threads, 10 at a time is expensive. It's generally better to start 10 threads and let each thread process 100 requests. A Thread pool normally has a single queue of requests when a thread is done working on a request it simply gets the next request in order & processes it...
Using the ISynchronizeInvoke interface you could setup the ThreadPool so that it was able to raise an event on your main Thread (your UI thread) to notify it when all the requests were done... (The thread pool object would have an ISynchronizeInvoke variable, when the last request finished it would use ISynchronizeInvoke.Invoke to invoke a delegate, that raised an event. The ISynchronizeInvoke variable would hold an instance of your form, causing ISynchronizeInvoke.Invoke to run on the UI thread. Using ISynchronizeInvoke to raise the event would mean the main form would not need to poll to see if all the requests were done or not...
Hope this helps Jay
| | | Reply: by:Jay B. Harlow [MVP - Outlook]
| | | Manuel, It sounds like you simply want to use the System.Threading.ThreadPool or roll your own Thread Pool.
System.Threading.ThreadPool allows by default 25 threads per processor. To use it you would simply use ThreadPool.QueueUserWorkItem 1000 times with the same function address... See System.Threading.ThreadPool for details...
Alternatively if you want to limit it to 10 threads, you will need to write your own Thread Pool. I would create a new Thread Pool class that started 10 Threads. My Thread Pool class would have a System.Collections.Queue object that represented the requests. Each thread would dequeue an item and work on it. I would have a special request or other mechanism available to tell each thread that it is time to exit. I would also include a single AutoResetEvent, that each thread would wait on to see if an item is in the Queue. Plus there should be a padlock object (I normally use "New Object") that you can SyncLock on to ensure that reading & writing to the queue is properly synchronized.
Writing your own thread pool will not be as easy as I am making it sound, however it is fairly easy! The above should be enough to get you started, alternatively you could search google for a sample. Tom's code may help you get started...
Note I've done the above & posted to the newsgroup my alternative above using a single thread.
Hope this helps Jay
|
|
|
|
|
0 Comments:
Post a Comment