Sunday, July 01, 2007 12:07 PM
We have heaard of lot of thread safe practices, semaphore , mutex and others. One goal of all ,is to create some app/tool which excecutes task faster than traditional single process app. One of the best example of this, creating some console importing tool.
As i said , there are loads of way to make an app multi-threaded, but the simpliest but robust one , which i am going to speak in the next few lines.
Let's kick off by creating a global List/Array items, that will hold the list of items to work on , there will be a global index and a object instace , which we will use as a "lock" key.
static
object workerLocker = new object(); private static int _Index = 0; private static IList<SomeObject> objects= null; static
int runningWorkers = 0; Next, there will be an starter routine that will fire off some specific amount of thread , which is definined in app.config
public static int MAX_MODULE_COUNT = int.Parse(ConfigurationSettings.AppSettings["Max_Count"]); Let's say in main method we have something like :
objects = GetListOfItems(); // objects defined globally
runningWorkers = objects .Count;
List<Thread> threadList = new List<Thread>();
for (int index = 0; index < THREAD_COUNT; index++)
{
Thread thread = new Thread(WorkerRoutine);
thread.Start();
threadList.Add(thread);
}
Now, we have to make sure, while the threads are running the app does not quits , so we will do a little join , that will wait untill all the threads are finished up.
foreach
(Thread thread in threadList) {
thread.Join();
//Console.WriteLine(i++); }
Now, inside the WorkingRountine(our main process routine), we will need to take a item from the list , increase the index and need to work on it. But the main theme here , the thread will not quit unless all the items are worked on. Lets say, you have started with 100 threads, those will remain active unless all the items get dried out. The concept will work more like a factory production line.
Indside "WorkingRoutine" we will the following:
SomeObject object= null; while (_Index < runningWorkers) {
lock (workerLocker) {
object= objects[_Index++];
}
try {
// do something useful here
}
catch (Exception ex) {
//log the exception or do whatever appropiate }
} // end loop
Here , to remember that "lock" has to be done for very little amount of time, so that no two thread cant access the list at the same time. And , as soon as, we took an object from the queue and increased the index, we open it out.
Although, there are lots of way to achive this out, i found it really easy to implement and effective.