Если вам нужно подождать, пока все задачи будут обработаны, вам нужно справиться с этим самостоятельно. Все потоки ThreadPool являются фоновыми потоками и не будут поддерживать приложение в рабочем состоянии.
Это относительно чистый способ справиться с ситуацией такого типа:
using (var mre = new ManualResetEvent(false))
{
int remainingToProcess = workItems.Count(); // Assuming workItems is a collection of "tasks"
foreach(var item in workItems)
{
// Delegate closure (in C# 4 and earlier) below will
// capture a reference to 'item', resulting in
// the incorrect item sent to ProcessTask each iteration. Use a local copy
// of the 'item' variable instead.
// C# 5/VS2012 will not require the local here.
var localItem = item;
ThreadPool.QueueUserWorkItem(delegate
{
// Replace this with your "work"
ProcessTask(localItem);
// This will (safely) decrement the remaining count, and allow the main thread to continue when we're done
if (Interlocked.Decrement(ref remainingToProcess) == 0)
mre.Set();
});
}
mre.WaitOne();
}
При этом, как правило, лучше "группировать" вместе ваши рабочие элементы, если у вас их тысячи, а не рассматривать их как отдельные рабочие элементы для пула потоков. Это некоторые накладные расходы, связанные с управлением списком элементов, и, поскольку вы не сможете обрабатывать 22000 одновременно, лучше сгруппировать их в блоки. Имея по одному рабочему элементу каждый процесс 50 или около того, вероятно, немного увеличит вашу общую производительность ...