Эффективность многопараметрических потоков - PullRequest
2 голосов
/ 01 ноября 2008

Будет ли более элегантный способ написания следующего синтаксиса?

        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 ]

7 голосов
/ 01 ноября 2008

Зачем вам начинать тему, а затем сразу присоединяться к ней?

Я бы обычно делал что-то вроде этого:

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();
}
2 голосов
/ 01 ноября 2008

Еще одна опция (в .NET 4.0 или с CTP) будет иметь вид Parallel.ForEach. Впрочем, не обязательно жизнеспособный. Я также видел хорошую запись в блоге (не помню, кто), которая использовала IDisposable здесь - то есть

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

где метод Dispose () сделал соединение в потоке, который был создан - то есть, когда вы вышли из блока, все завершено. Довольно мило.

0 голосов
/ 01 ноября 2008

Почему бы вашим параметрам не быть частью класса, не задать им свойства и не заблокировать методы 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;
}

Установите блокировку вокруг этого фрагмента (т. Е. Список объектов и фрагментов, каждый из которых имеет блокировку и т. Д.), Чтобы, когда поток получил доступ к своему фрагменту, он мог в конечном итоге заявить, что он «готов», освободить блокировка, и тогда у вас может быть функция окончательного слияния, которая просто ожидает, чтобы эти готовые логические значения были отмечены. Таким образом, если один из потоков умирает до завершения установки, и вы знаете, что поток мертв, то вы также знаете, что поток не завершил свою работу, и вам необходимо выполнить восстановление после ошибки; если вы просто ждете, когда произойдет соединение, поток все равно мог испортить свой фрагмент.

Но есть много таких конкретных идей для реализации, основанных на проблеме, которую вы пытаетесь решить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...