多参数化线程效率

时间:2008-10-31 21:49:59

标签: .net multithreading parameters

是否有更优雅的方式编写以下语法?

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

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

假设我们想传递20个不同的值,设置它的最佳方法是什么?在最后循环并加入?

如果未实例化新线程(如下所示),则无法重新启动线程。例如:

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

3 个答案:

答案 0 :(得分:7)

你为什么要开始一个线程然后立即加入呢?

我通常会这样做:

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

答案 1 :(得分:2)

另一个选项(在.NET 4.0中,或使用CTP)将是Parallel.ForEach的一种形式。但是,不一定可行。我还看到了一个在这里使用IDisposable的好博客条目(不记得是谁),即

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

其中Dispose()方法在生成的线程上进行了连接 - 即退出块时,一切都已完成。很可爱。

答案 2 :(得分:0)

为什么不让你的参数成为类的一部分,使它们成为属性,并让get / set方法锁定它们?如果您有足够的参数,请将参数对象本身作为对象的属性,然后锁定该参数块。如:

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

然后按照已建议的方式执行您的线程池。这样,您就可以锁定数据访问,这样如果所有线程都需要它,它们就可以相互等待。

如果您正在为图像处理(可以同时完成许多并行对象)这样做,那么将数据分解为个性化块可能更好。 IE,比如你想在一个较大的图像上运行一些卷积,所以想把它分成两半。然后,您可以使用“Fragmentimage”函数创建您将单独处理的图像块,然后使用“MergeFragments”函数调用以加入所有结果。所以你的片段看起来像:

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

锁定该片段(即,一个对象和片段的列表,每个都有一个锁等等),这样当线程访问它的片段时,它最终可以声明它已经“完成”,释放锁定,然后你可以有一个最终的合并函数,只等待那些已经标记的布尔值。这样,如果其中一个线程在设置完成之前就死了,并且你知道线程已经死了,那么你也知道线程没有完成它的工作,你需要做一些错误恢复;如果你只是等待连接发生,那么线程可能仍然搞砸了它的片段。

但是,基于您试图解决的问题,有很多具体的想法要实施。