2010-09-29 8 views
0

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

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-секундной задержки для каждой нити расстраивает.

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

благодаря ...

Sam

ответ

6

Вам необходимо пройти каждый новый поток, совершенно новый объект. В настоящее время все они получают ссылку на тот же объект в главном потоке, т.е. 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.

+0

Perfect. Я не очень беспокоюсь о порядке, просто имея возможность идентифицировать потоки, когда они происходят. Спасибо за вашу помощь! – Sam

+0

@Sam - рад, что это помогло –