I have written a program in c# for quick sort using multithreading. but the code has a problem. the array is not sorted properly. i think it is because the parent thread terminates soon before the child threads sort the array. i am attaching the code herewith. kindly help me.any help is highly appreciated. thanks in advance.

Beulah

using System; 
using System.Threading; 
using System.Collections; 

namespace QSort 
{ 
/// <summary> 
/// Summary description for Class1. 
/// </summary> 
class Class1 
{ 
/// <summary> 
/// The main entry point for the application. 
/// </summary> 
[STAThread] 
static void Main(string[] args) 
{ 
Class1 class1 = new Class1(); 
} 


//public int[] a = new int[10000000]; 
//added 
private const int MAX=6; 
public int[] a = new int[MAX]; 


public Class1() 
{ int choice=1; 
while (choice<3) 
{ 
Random random = new Random(); 
/*for(Int32 i=0;i<10000000;++i) 
a[i] = random.Next(100000000);*/ 
//added 
a[0]=20; 
a[1]=10; 
a[2]=40; 
a[3]=30; 
a[4]=60; 
a[5]=50; 
//}added 
ArrayList list = new ArrayList(); 
list.Add(0); 
list.Add(a.Length-1); 

DateTime startTime = DateTime.Now; 
Console.Write("1. SigleThreaded Sort\n2.MultithreadSort\nEnter Choice : "); 
choice=Convert.ToInt32(Console.ReadLine()); 
switch(choice) 
{ 
case 1: 
startTime = DateTime.Now; 
QSort(0, a.Length-1); 
break; 

case 2: 
//multithreading startTime = DateTime.Now; 
QSort(list); 
break; 
default: 
break; 
} 
if (choice<3) 
{ 
Console.WriteLine("Time Taken to sort "+a.Length.ToString() +" elements = "+(DateTime.Now.Subtract(startTime)).TotalMilliseconds.ToString()+" MilliSeconds"); 
//added 
for (int index=0; index<MAX; index++) 
Console.WriteLine(a[index]); 
} 

} 
} 



//this works fine 
public void QSort( int left, int right )//singlethreaded 
{ 
int pivot, lhold, rhold; 

lhold = left; 
rhold = right; 
pivot = a[left]; 

while( left < right ) 
{ 
while( (a[right] >= pivot) && (left < right) ) 
{ 
right--; 
} 

if( left != right ) 
{ 
a[left] = a[right]; 
left++; 
} 

while( (a[left] <= pivot) && (left < right) ) 
{ 
left++; 
} 

if( left != right ) 
{ 
a[right] = a[left]; 
right--; 
} 
} 

a[left] = pivot; 
pivot = left; 
left = lhold; 
right = rhold; 

if( left < pivot ) 
{ 
QSort( left, pivot-1 ); 
} 

if( right > pivot ) 
{ 
QSort( pivot+1, right ); 
} 
} 


//i have problem in this method 
public void QSort(object listObject) //Multithreaded 

{ 
Int32 left = (Int32)((ArrayList)listObject)[0]; 
Int32 right = (Int32)((ArrayList)listObject)[1]; 
int pivot, lhold, rhold; 

lhold = left; 
rhold = right; 
pivot = a[left]; 
lock(a) 
{ 
while( left < right ) 
{ 

while( (a[right] >= pivot) && (left < right) ) 
{ 
right--; 
} 

if( left != right ) 
{ 
a[left] = a[right]; 
left++; 
} 

while( (a[left] <= pivot) && (left < right) ) 
{ 
left++; 
} 

if( left != right ) 
{ 
a[right] = a[left]; 
right--; 
} 
} 

a[left] = pivot; 
pivot = left; 
left = lhold; 
right = rhold; 
} 

if( left < pivot ) 
{ 
ArrayList list = new ArrayList(); 
list.Add(left); 
list.Add(pivot-1); 
ThreadPool.QueueUserWorkItem(new WaitCallback(QSort),list); 
} 

if( right > pivot ) 
{ 
ArrayList list = new ArrayList(); 

list.Add(pivot+1); 
list.Add(right); 
ThreadPool.QueueUserWorkItem(new WaitCallback(QSort),list); 
} 
} 
} 
}

Dani AI

Generated

Two separate issues are visible in the thread: the process exiting before ThreadPool work items finish, and a locking pattern that serializes all partitions so threads never run in parallel. was right to suspect the main thread ending, and and point in useful directions (dedicated Threads and WaitHandles). The practical fix is to (1) keep the process alive until all queued work is done and (2) avoid locking the entire array during partitioning.

A simple, robust pattern is a shared completion counter plus a ManualResetEvent. Initialize the counter to 1 (for the root work), call the root partition, increment the counter before queuing any subtask, and at the end of each worker decrement the counter; when it hits zero signal the event so the main thread can WaitOne. This avoids the 64-handle limit of WaitHandle.WaitAll and works nicely with ThreadPool threads.

Example pattern (concept only — adapt to your QSort method):

static ManualResetEvent allDone = new ManualResetEvent(false);
static int pending = 1; // root work

// before queuing a subtask:
Interlocked.Increment(ref pending);
ThreadPool.QueueUserWorkItem(QSort, subList);

// at the end of QSort (worker finished):
if (Interlocked.Decrement(ref pending) == 0)
    allDone.Set();

// in main, after starting root QSort:
allDone.WaitOne();

Additional notes: remove the broad lock(a) around the whole partition — it forces serialization and likely hides correctness problems. Quicksort partitions operate on disjoint index ranges, so keep only small critical sections (if any). Also avoid spawning work for tiny partitions (sort them inline) to prevent excessive queueing. If using dedicated Thread objects instead of the ThreadPool, create them as foreground threads and use Join() from main to wait for completion.

Recommended Answers

All 3 Replies

I by no means am an expert in threading but here is what i can gather from this.
you are using 'ThreadPool.QueueUserWorkItem' which queues the item into the current main thread.
What you need to do is create a whole new thread which i did not see.
which is something like:

myThread = new System.Threading.Thread(new 
   System.Threading.ThreadStart(myStartingMethod));
myThread.Start();

that creates a seperate thread from the main with a method to initialze it.
the locks go in functions that are shared by more then one thread, which could be a single function to change data in the array then a seperate function for sorting.

thank u for ur reply. but my code also allots a separte thread from the thread pool. the prob is how to prevent the main thread from terminating b4 the child thread terminates.

Beulah

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.