Текущая реализация: ожидает сбора значений parallelCount
, использует 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
и добавить его в некоторую коллекцию только тогда, когда есть спрос на него.Является ли использование очереди здесь хорошей идеей?
Спасибо.