.NET предоставляет пул потоков, который вы можете использовать. System.Threading.ThreadPool.QueueUserWorkItem()
говорит потоку в пуле сделать для вас некоторую работу.
Если бы я проектировал это, я бы не стал фокусироваться на сопоставлении потоков с вашими ресурсами HW. Вместо этого я бы выставил блокируемый объект для каждого ресурса HW - это может быть просто массив или очередь из 5 объектов. Затем для каждого имеющегося у вас вычисления вызовите QueueUserWorkItem()
. Внутри метода, который вы передаете в QUWI, найдите следующий доступный блокируемый объект и заблокируйте его (иначе, удалите из очереди). Используйте ресурс HW, затем повторно поставьте объект в очередь, выйдите из метода QUWI.
Не имеет значения, сколько раз вы звоните в QUWI; может удерживаться не более 5 блокировок, каждая из которых защищает доступ к одному экземпляру вашего специального аппаратного устройства.
Страница документа для Monitor.Enter()
показывает, как создать безопасную (блокирующую) очередь, к которой могут обращаться несколько работников. В .NET 4.0 вы бы использовали встроенную коллекцию BlockingCollection - это то же самое.
Это в основном то, что вы хотите. Кроме не звоните Thread.Create()
. Используйте пул потоков.
cite: Преимущество использования Thread.Start по сравнению с QueueUserWorkItem
// assume the SafeQueue class from the cited doc page.
SafeQueue<SpecialHardware> q = new SafeQueue<SpecialHardware>()
// set up the queue with objects protecting the 5 magic stones
private void Setup()
{
for (int i=0; i< 5; i++)
{
q.Enqueue(GetInstanceOfSpecialHardware(i));
}
}
// something like this gets called many times, by QueueUserWorkItem()
public void DoWork(WorkDescription d)
{
d.DoPrepWork();
// gain access to one of the special hardware devices
SpecialHardware shw = q.Dequeue();
try
{
shw.DoTheMagicThing();
}
finally
{
// ensure no matter what happens the HW device is released
q.Enqueue(shw);
// at this point another worker can use it.
}
d.DoFollowupWork();
}