Recursive Directory Searches in C# (Part 2) (
Page 1 of 2 )
In Part 2 of this article, Rick continues his discussion on the recursing directories. This week Rick shows you how to add threading and callbacks to the program so the program is a little friendlier to the computer.
Threading the Method
Hey, but wait a minute. The process we covered in the last article may take some time. It may even take several minutes. And during this time the CPU devotes all of your program's cycles to the recursive method calls. This could wreak havoc on your program. None of the user interface objects will respond during the cycle-hogging process. And users get very frustrated when that happens. This is not something you want to inflict on your user's computer.
To solve this dilemma you need to perform recursive calls from a spawned thread. This way, the new thread will devote all of its CPU cycles to the new thread's process, but your program will function normally. All of the user interface objects will work.
ADVERTISEMENT
Make sure that you add a using statement so that System.Threading can be referenced as follows:
using System.Threading;
It's very easy to create and spawn a thread process. The following code shows how to spawn a thread that runs the DoSomething method and starts it going.
Thread thread = new Thread(
new ThreadStart(DoSomething) );
Thread.Start();
The DoSomething method continues executing until it is done and exits (with a return), the thread object that was created stops (usually with the Suspend method), or the thread object is destroyed.
You can check on whether the thread method is finished. This might be helpful if you've spawned a thread that must complete a task before you can do something else. In order to check a thread to see if it's still running, you can use code similar to the following:
if(m_Thread.ThreadState == ThreadState.Running)
{
// Act on the knowledge that
// the thread is finished.
}
There is one last issue to deal with. The method that you kick off with the thread can't take any arguments. That makes it more difficult for us since we initially called the ExamineDir method with two parameters. The solution for this is to kick off a method that then calls the ExamineDir method. The entire code to examine the C drive starting at its root directory from inside a thread is as follows:
// Thread variable.
static private Thread m_Thread;
// This method is kicked off by the Thread.Start method.
static public void StartSearch()
{
// Call our ExamineDir method.
ExamineDir(@"C:\", 0);
}
// This is the ExamineDir method we've been using.
static public void ExamineDir(string strDir,int nIndex)
{
try
{
foreach (string strDirName in Directory.GetDirectories(strDir))
{
string strIndent = new String( ' ', nIndex );
Console.WriteLine(strIndent + strDirName);
ExamineDir(strDirName, nIndex+1);
}
}
catch{}
}
static void Main(string[] args)
{
// Create a thread object.
m_Thread = new Thread( new ThreadStart(StartSearch));
// Start the thread. This kicks off the StartSearch method.
m_Thread.Start();
// Wait until the thread is done.
while (m_Thread.ThreadState == ThreadState.Running)
{
Thread.Sleep(10);
}
Console.WriteLine( "\n\n***Done" );
}
Many of the programs I write need a way for the thread to bail out in response to something that happens in the main program. I find that it's usually best to use a flag that the main program sets to true when it needs the thread to quit. During execution the thread checks the flag and bails out when it is set to true. The following addition to the start of the ExamineDir method can be used: