Параметры ThreadPool - PullRequest
       7

Параметры ThreadPool

0 голосов
/ 29 сентября 2010

Я тестирую простое решение для пула потоков, прежде чем помещать его в свое приложение, но результаты, которые я вижу, не имеют смысла для меня.У меня есть простая форма с одной кнопкой на нем.Эта кнопка запускает следующий цикл:

private void button1_Click(object sender, EventArgs e)
{
    MyTestThread oTask = new MyTestThread ();
    MyThreadInfo oTaskParameters = new MyThreadInfo();
    for (int i = 1; i <= 5; i++)
    {
        objTaskParameters.MyGuid = Guid.NewGuid();
        objTaskParameters.MyNumber = i;
        ThreadPool.QueueUserWorkItem(new WaitCallback(objTask.ProcessDataForNTime), objTaskParameters);
    }
    Console.WriteLine("All threads have been queued for processing...");
}

Класс, который он вызывает, выглядит следующим образом.У него есть класс параметров MyThreadInfo, а затем класс MyTestThread зацикливается на 10 секунд перед завершением.

public class MyThreadInfo
{
    public int MyNumber;
}

public class MyTestThread 
{
    public void ProcessDataForNTime(Object oParameters)
    {
        //We pass parameters
        MyThreadInfo oThread = (MyThreadInfo)oParameters;
        int threadNo = oThread.MyNumber;

        Console.WriteLine("thread {0} started...", threadNo);

        int iN = 10; //Delay for 10 seconds
        DateTime dteStart = DateTime.Now;
        do
        {
            System.Threading.Thread.Sleep(1000); //Wait a second before we look again
        } while (dteStart.AddSeconds(iN) > DateTime.Now);

        Console.WriteLine("thread {0} completed...", threadNo);
    }
}

Я ожидаю, что результаты этого будут отображаться примерно так в моем журнале консоли / вывода / отладки.Проходя по приложению, я действительно вижу это:

thread 1 started...
thread 2 started...
thread 3 started...
thread 4 started...
thread 5 started...
All threads have been queued for processing...
thread 1 completed...
thread 2 completed...
thread 3 completed...
thread 4 completed...
thread 5 completed...

НО, если я запускаю приложение на полной скорости, не проходя через код или точки останова, оно выдает следующее:

All threads have been queued for processing...
thread 5 started...
thread 5 started...
thread 5 started...
thread 5 started...
thread 5 started...
thread 5 completed...
thread 5 completed...
thread 5 completed...
thread 5 completed...
thread 5 completed...

Что такое пошаговое выполнение кода, который заставляет его работать?Я заметил, что добавление Thread.Sleep (1000) (1 секунда) в цикл заставляет приложение правильно маркировать потоки, но я пытаюсь разработать быстрое многопоточное приложение и идею добавить задержку в 1 секунду.для каждого потока это расстраивает.

Кто-нибудь может дать мне некоторое представление о том, почему я вижу это поведение?

спасибо ...

Сэм

1 Ответ

6 голосов
/ 29 сентября 2010

Вам необходимо передать каждому новому потоку совершенно новый объект.В настоящее время все они получают ссылку на один и тот же объект в основном потоке, то есть oTaskParameters

Попробуйте сделать это, сделав MyNumber устанавливаемым в качестве параметра в конструкторе MyThreadInfo:

for (int i = 1; i <= 5; i++)
{
    MyThreadInfo oTaskParameters = new MyThreadInfo(i);
    objTaskParameters.MyGuid = Guid.NewGuid();
    ThreadPool.QueueUserWorkItem(new WaitCallback(objTask.ProcessDataForNTime), objTaskParameters);
}

MyThreadInfo(int i) : MyNumber(i)
{
  // rest of construction logic
}

Это изменение означает, что каждый новый поток получает непересекающийся экземпляр MyThreadInfo с соответствующим образом установленным идентификатором этого потока.

По-прежнему нет гарантии, что потоки будут распечатывать свои идентификаторы в порядке возрастания.Вы должны будете ввести некоторый тип очереди / обработки FIFO, чтобы обеспечить это.Подробно обсуждается этот вопрос ordering of thread execution using Threadpool.QueueUserWorkItem.

...