views:

401

answers:

3

Would there a more elegant way of writing the following syntax?

        Thread t0 = new Thread(new ParameterizedThreadStart(doWork));
        t0.Start('someVal');
        t0.Join();

        Thread t1 = new Thread(new ParameterizedThreadStart(doWork));
        t1.Start('someDiffVal');
        t1.Join();

Presuming we want to pass 20 different values, what would the best way of setting this up be? Looping through and joining at the end?

If a new thread isn't instantiated (like below), it errors that the thread can't be restarted. For example:

        Thread t1 = new Thread(new ParameterizedThreadStart(doWork));
        t1.Start('someVal');
        t1.Start('someDiffVal');
+5  A: 

Why would you start a thread and then join against it immediately?

I'd normally do something like this:

List<Thread> threads = new List<Thread>();

foreach (string item in items)
{
    string copy = item; // Important due to variable capture
    ThreadStart ts = () => DoWork(copy); // Strongly typed :)
    Thread t = new Thread(ts);
    t.Start();
    threads.Add(t);
}

foreach (Thread t in threads)
{
    t.Join();
}
Jon Skeet
This was really interesting and good - although I wasn't sure what you were doing programatically with ThreadStart ts = () => DoWork(copy);
dotnetdvlpr
@dotnetdvlpr: That's a lambda expression. It's a simple way of creating a delegate in C# 3.0.
Jon Skeet
+2  A: 

One other option (in .NET 4.0, or with the CTP) would be a form of Parallel.ForEach. Not necessarily viable yet, though. I also saw a good blog entry (can't remember by who) that used IDisposable here - i.e.

using(StartThread(arg1))
using(StartThread(arg2))
{
}

where the Dispose() method did a join on the thread that was spawned - i.e. when you exited the block, all are complete. Quite cute.

Marc Gravell
A: 

Why not have your parameters be part of the class, make them properties, and have the get/set methods lock around them? If you have enough parameters, make the parameter object itself a property of the object, and then lock that parameter block. As in:

class GonnaDoSomeThreading {
   private Object mBlockLock = new Object();
   private MyParameterBlock mBlock;
   public MyParameterBlock Block {
       get { 
            MyParameterBlock tmp;
            lock (mBlockLock){
                tmp = new MyParameterBlock(mBlock); //or some other cloning
            }
            return tmp; //use a tmp in order to make sure that modifications done
                        //do not modify the block directly, but that modifications must
                        //be 'committed' through the set function
       }
       set { lock (mBlockLock){ mBlock = value; } } 
   }
}

And then do your thread pool as already suggested. That way, you've got locks around the data access, so that if all of your threads need it, they can wait on one another.

If you're doing this for something like image processing (where a lot of parallel objects can be done at once), then it might be better to break up your data into individualized chunks. IE, say you want to run some convolution over a largish image, and so want to break it up into two halves. Then, you can have a 'Fragmentimage' function which creates the image blocks that you're going to work on individually, and then a 'MergeFragments' function call to join all the results. So your fragment could look like:

class ThreadWorkFragment {
    <image type, like ushort>[] mDataArray;
    bool mDone;
}

Put a lock around that fragment (ie, a list of objects and fragments, with each having a lock and so forth), so that when the thread accesses it's fragment, it can eventually state that it's 'done', release the lock, and then you can have a final merge function which just waits for those done booleans to be flagged. That way, if one of the threads dies before setting done, and you know the thread's dead, then you also know that the thread didn't finish its work and you need to do some error recovery; if you just wait for a join to happen, the thread could still have messed up its fragment.

But there's a lot of those kinds of specific ideas to implement, based on the problem you're trying to solve.

mmr