2

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

        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');
4

3 回答 3

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();
}
于 2008-10-31T21:54:55.703 回答
2

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

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

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

于 2008-10-31T22:00:58.733 回答
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;
}

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

但是,根据您要解决的问题,有很多特定的想法需要实施。

于 2008-10-31T22:15:13.557 回答