Hi,
this looks like a perfect scenario for a producer / consumer type of solution. Where there are threads putting data into a queue and other threads processing those items as they become available. So you can queue a number of WMI requests and then worker threads will pick those off while there are items still left in the queue. Below is an example of how you can do this, the code will create a number of threads, each thread will wait using Monitor.Wait until it is signaled by the consumer thread which uses Monitor.Pulse to wake up a thread. The key is that if a Monitor.Pulse call takes place and no thread is waiting on the lock then the pulse will appear not to have happened, so threads keep processing while there are items in the queue, only waiting while the queue is empty. Hope this makes sense:
using System;
using System.Collections.Generic;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ProducerConsumer pc = new ProducerConsumer(5);
//Create a stream of data to be processed
for (int i = 0; i < 100; ++i)
{
pc.Produce(i.ToString());
}
//Indicate all items are queued so threads will exit
//when queue is empty
pc.AllItemsAdded();
//Wait a while for data to be processed.
//Ideally have a syncronization method to know when all worker items are complete
Thread.Sleep(60000);
}
}
class ProducerConsumer
{
private Random random = new Random();
private bool noMoreWork = false;
private readonly object workItemLock = new object();
private Queue<string> workItems = new Queue<string>();
public ProducerConsumer(int numberOfWorkerThreads)
{
//Create the required number of worker threads
for (int i = 0; i < numberOfWorkerThreads; ++i)
{
new Thread(new ThreadStart(Consume)).Start();
}
}
//Add a new work item to the queue
public void Produce(string wmiRequest)
{
lock (this.workItemLock)
{
//Add new work item to the list
workItems.Enqueue(wmiRequest);
//Notify a thread that data has arrived
Monitor.Pulse(this.workItemLock);
}
}
private void Consume()
{
string wmiRequest;
while (true)
{
lock(this.workItemLock)
{
//Check to see if there is any work to do
while(this.workItems.Count == 0)
{
//If user has indicated there will be
//no more work then let the thread exit
if (this.noMoreWork)
{
return;
}
//Wait for work
Monitor.Wait(this.workItemLock);
}
//Take an item of the queue
wmiRequest = this.workItems.Dequeue();
}
//Do the work outside of the lock so that items can be
//added to the queue and removed by other threads
//Simulate work time
Thread.Sleep(this.random.Next(3001));
Console.WriteLine(wmiRequest);
}
}
//Indicates that there will be no more work, once the
//queue is empty the worker threads can exit
public void AllItemsAdded()
{
lock (this.workItemLock)
{
this.noMoreWork = true;
//Wake everyone up if they are waiting for data
Monitor.PulseAll(this.workItemLock);
}
}
}
}
Mark.
|