Custom Thread Manager In C#
Friday, June 19, 2009 12:59:31 PM
I was recently working on a project that required me to limit the number of background threads that could be executing at any given time. It could be my lack of knowledge of how the built in .Net classes work for managing thread execution, but I decided to embark on a quest to work up my own solution to this problem. The below code was hastily written to solve the problem at hand, but you should be able to see the underlying concept I used. Bare with me.
First, I needed some thread parameters so that I could pass these to my scanner. Here is the class that I created to handle this. Name is the name of the Domain Controller we are going to query.
public class ThreadParams
{
public string BaseOU = "";
public string Name = "";
public ThreadParams(string baseOU, string name)
{
BaseOU = baseOU;
Name = name;
}
}
Next I created a class that acted as the shell of my scanner, called LastLogonScanner.
public class LastLogonScanner
{
private System.DirectoryServices.ActiveDirectory.DomainControllerCollection _domainControllers;
public System.DirectoryServices.ActiveDirectory.DomainControllerCollection DomainControllers
{
get
{
return _domainControllers;
}
set
{
_domainControllers = value;
}
}
private System.DirectoryServices.ActiveDirectory.Domain _domain;
public System.DirectoryServices.ActiveDirectory.Domain Domain
{
get
{
return _domain;
}
set
{
_domain = value;
}
}
public LastLogonScanner()
{
_domain = GetDomain();
EventLogger(String.Format("Enumerating DCs for domain {0}", _domain.Name));
_domainControllers = GetDCList(_domain);
EventLogger(String.Format("Found {0} DCs", _domainControllers.Count.ToString()));
}
public System.DirectoryServices.ActiveDirectory.Domain GetDomain()
{
return System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain();
}
public System.DirectoryServices.ActiveDirectory.DomainControllerCollection GetDCList(System.DirectoryServices.ActiveDirectory.Domain domain)
{
return domain.DomainControllers;
}
}
Now, here is where the real meat of it lies. For each DC it will create a thread. Then it will monitor each thread to see if it has started, if it has not been started and there are less than 5 running threads, start up a new thread and pass the base OU and the Domain Controller you wish to scan to it.
public void GetLastLogonTimes(string baseOU)
{
List<Thread> threads = new List<Thread>();
foreach (System.DirectoryServices.ActiveDirectory.DomainController dc in _domainControllers)
{
Thread t = new Thread(new ParameterizedThreadStart(GetUsersForDC));
t.Name = dc.Name;
threads.Add(t);
}
while (true)
{
bool threadsActive = false;
int runningCount = 0;
int pendingCount = 0;
foreach (Thread t in threads)
{
if (t.IsAlive)
{
runningCount += 1;
}
if (t.ThreadState == ThreadState.Unstarted)
{
pendingCount += 1;
}
}
if (runningCount < 5)
{
if (pendingCount > 0)
{
foreach (Thread t in threads)
{
if (t.ThreadState == ThreadState.Unstarted)
{
ThreadParams tp = new ThreadParams(baseOU, t.Name);
t.Start((object)tp);
break;
}
}
}
}
foreach (Thread t in threads)
{
if (t.IsAlive)
{
threadsActive = true;
break;
}
}
if (!threadsActive)
{
break;
}
}
}
A bit of a kludge, I know, but it was very affective.
You can download the full program here.