2010-11-19 2 views
1

Текущая реализация: ожидается, что значения собираются parallelCount, использует ThreadPool для обработки значений, до тех пор, пока все потоки не завершатся, не заберут еще один набор значений и так далее ...C# - Передача данных обратно из ThreadPool в главную нить

Код:

private static int parallelCount = 5; 
private int taskIndex; 
private object[] paramObjects; 

// Each ThreadPool thread should access only one item of the array, 
// release object when done, to be used by another thread 
private object[] reusableObjects = new object[parallelCount];  

private void MultiThreadedGenerate(object paramObject) 
{ 
    paramObjects[taskIndex] = paramObject; 
    taskIndex++; 

    if (taskIndex == parallelCount) 
    { 
     MultiThreadedGenerate(); 

     // Reset 
     taskIndex = 0; 
    } 
} 

/* 
* Called when 'paramObjects' array gets filled 
*/ 
private void MultiThreadedGenerate() 
{ 
    int remainingToGenerate = paramObjects.Count; 

    resetEvent.Reset(); 

    for (int i = 0; i < paramObjects.Count; i++) 
    { 
     ThreadPool.QueueUserWorkItem(delegate(object obj) 
     { 
      try 
      { 
       int currentIndex = (int) obj;  

       Generate(currentIndex, paramObjects[currentIndex], reusableObjects[currentIndex]); 
      } 
      finally 
      { 
       if (Interlocked.Decrement(ref remainingToGenerate) == 0) 
       { 
        resetEvent.Set(); 
       } 
      } 
     }, i); 
    } 

    resetEvent.WaitOne();  
} 

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

[1] Сбор значений в paramObjects и синхронизации с использованием resetEvent можно избежать, так как нет зависимости между потоками (или текущим набором значений со следующим набором значений). Я делаю это только для управления доступом к reusableObjects (когда выполняется обработка paramObjects, я знаю, что все объекты в reusableObjects являются бесплатными, поэтому taskIndex сбрасывается, и каждая новая задача следующего набора значений будет иметь свой уникальный «reusableObj ' работать с).

[2] Не существует реального соединения между размером reusableObjects и количеством потоков, используемых ThreadPool. Я мог бы инициализировать reusableObjects, чтобы иметь 10 объектов и сказать из-за некоторых ограничений, ThreadPool может запускать только 3 потока для моего метода MultiThreadedGenerate(), тогда я теряю память.

Так, избавившись от paramObjects, как можно выше код будет уточнена таким образом, что как только один поток завершает свою работу, что нить возвращает его taskIndex (или reusableObj) не используется и больше не нуждается, так что это становится доступным для следующего значения. Кроме того, код должен создать reUsableObject и добавить его в некоторую коллекцию только тогда, когда есть спрос на нее. Является ли использование очереди здесь хорошей идеей?

спасибо.

+0

Какая версия .Net вы? –

+0

Я использую .NET 3.5 – alhazen

ответ

5

На самом деле нет причин для самостоятельного ручного управления потоками и управления задачами. Вы можете реструктурировать эту модель с более слабосвязанной моделью, используя Task Parallel Library (и, возможно, System.Collections.Concurrent для сравнения результатов).

Производительность может быть улучшена, если вам не нужно ждать полного дополнения работы перед передачей каждого Task для обработки.

TPL пришел в .Net 4.0, но был back-ported to .Net 3.5. Загрузить here.

+0

+1 Я не знал о заднем порту, поэтому спасибо за информацию. –

+0

@Brian - Я видел рефрен к этому, но не отслеживал его раньше, он очень полезен, если хорошо скрыт. –

Смежные вопросы