Burdock
Burdock

Reputation: 1105

Proper way to Thread a foreach loop

I have been cracking at this for the last 30 minutes, trying to thread a simple foreach loop which is casting some error no matter what I do (First time not using a threading framework so I'm most likely making some silly syntax mistake)

Sadly I cant use Parallel.For due to having to stay .net 3.5 or below... Can someone tell me the right way to do this so I can go back to not wanting to scream!!

Sudo code

void SomeMethod
{
    foreach(Touch Input in Inputlist){
        Thread thread = new Thread(new ThreadStart(this.FilterInput(Input)));
        thread.Start();
    }
}
void FilterInput(Input UnFilteredInput){
....
}

Edit: MonoDevelop is casting the following errors

  1. Expression denotes a value, where a type or method group was expected

  2. The best overloaded method match for System.Threading.Thread.Thread(System.Threading.ThreadStart) has some invalid arguments,

  3. Argument #1 cannot convert object expression to type System.Threading.ThreadStart

Upvotes: 2

Views: 454

Answers (1)

Scott Chamberlain
Scott Chamberlain

Reputation: 127563

First of all, for something like this you should use a lighter weight ThreadPool intead of a full Thread. (Also you did make some casting mistakes too, the thread pool version uses the same style as Thread so you can see the difference)

void SomeMethod
{
    foreach(Touch input in Inputlist){
        ThreadPool.QueueUserWorkItem(new WaitCallback(FilterInput), input);
    }
}
void FilterInput(object unCastUnFilteredInput){
    Touch UnFilteredInput = (Touch)unCastUnFilteredInput;
....
}

However I would still be worried about creating too many threads per second and would recomend some kind of blocking to meter the rate new threads can be created.

const int MaxConcurrentThreads = 4;

private readonly Semaphore _inputLimiter = new Semaphore(MaxConcurrentThreads,MaxConcurrentThreads);

void SomeMethod
{
    foreach(Touch input in Inputlist){
        _inputLimiter.WaitOne();
        ThreadPool.QueueUserWorkItem(new WaitCallback(FilterInput), input);
    }
}
void FilterInput(object unCastUnFilteredInput){
    try
    {
        Touch UnFilteredInput = (Touch)unCastUnFilteredInput;
        ....
    {
    finally
    {
        //use a try-finally so the semaphore still gets released in the event a exception happens in the .... region.
        _inputLimiter.Release();
    }
}

Upvotes: 4

Related Questions