hola a todos

ho un problemuccio ... ho sviluppato un piccolo software che funziona come un crawler web

il funzionamento è semplice ... io do una lista inziale, avvio N threads, ogni threads monitora la lista e quando è piena acquisisce la prima riga eliminandola, acquisisce i dati dal web aggiunge l'indirizzo letto ad una lista di indirizzi acquisiti e poi aggiunge gli indirizzi acquisiti validi di nuovo nella lista iniziale

il mio problema è che solo un thread per volta lavora :\
e la cosa la ritengo assurda!!!!!!!!!!!

ora siccome non so se è un errore mio a livello pratico o a livello logico (perché ovvimante è un'errore mio) volevo sapere se avevate avuto esperienze simili o comunque esperienze con l'accoppiata Threading e WebRequest

codice:
private void WebCrawlingThread()
{
	Random randomNumberGenerator = new Random(234432);
	WebClient webClient = new WebClient();
	Regex addressesRegex = new Regex("href=\"([^\"]+)\"", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);
	Regex queryStringRegex = new Regex("([^&]+)&?", RegexOptions.Compiled | RegexOptions.IgnoreCase);
	string address = "";

	System.Console.WriteLine("Thread <{0}> wait for all threads", Thread.CurrentThread.Name); System.Console.Out.Flush();

	while(terminateThreads == false && threadsCanStart == false)
	{
		Application.DoEvents();
	}
	
	System.Console.WriteLine("Thread <{0}> started", Thread.CurrentThread.Name); System.Console.Out.Flush();

	while(true)
	{
		Application.DoEvents();

		// Check if threads must exits
		if (terminateThreads == true)
		{
			break;
		}
		
		// Check if there are addresses in the address list
		Monitor.Enter(this.addressList);
		if (this.addressList.Count == 0)
		{
			Monitor.Exit(this.addressList);
			continue;
		}
		
		// Acquire the page
		address = (string)this.addressList[0];
		this.addressList.RemoveAt(0);
		Monitor.Exit(this.addressList);
		
		try
		{
			Monitor.Enter(this.threadStatus);
			this.threadStatus[Thread.CurrentThread.Name] = address;		// DOWNLOADING PAGE
			Monitor.Exit(this.threadStatus);

			// Download the page
			byte[] downloadedDataBytes = webClient.DownloadData(address);
			string downloadedDataString = System.Text.Encoding.ASCII.GetString(downloadedDataBytes);
			
			Monitor.Enter(this.downloadedDataSize);
			this.downloadedDataSize += (ulong)downloadedDataBytes.Length;
			Monitor.Exit(this.downloadedDataSize);

			// Check the page
			MatchCollection resultsAddresses = addressesRegex.Matches(downloadedDataString);
			ArrayList foundedAddresses = new ArrayList();
			for(int currentMatch = 0; currentMatch < resultsAddresses.Count; currentMatch++)
			{
				string extractedAddress = resultsAddresses[currentMatch].Groups[1].Value.Replace("&amp;", "&");
				if (
						foundedAddresses.Contains(extractedAddress) == false &&
						crawledAddressList.Contains(extractedAddress) == false &&
						extractedAddress.ToLower().StartsWith("http://") == true
					)
				{

					int queryStringStartPosition = extractedAddress.IndexOf("?");
					if (queryStringStartPosition > 0)
					{
						if (queryStringRegex.Matches(extractedAddress, queryStringStartPosition + 1).Count > 2)
						{
							continue;
						}
					}

					foundedAddresses.Add(extractedAddress);
				}
			}
			
			System.Console.WriteLine("Thread <{0}> downloaded data from {1} founded {2} links!", Thread.CurrentThread.Name, address, foundedAddresses.Count.ToString()); System.Console.Out.Flush();
			
			// Add datas to the list
			Monitor.Enter(this.addressList);
			this.addressList.AddRange(foundedAddresses.ToArray());
			Monitor.Exit(this.addressList);
		}
		catch(WebException e)
		{
			System.Console.WriteLine("Thread <{0}> exception, error type {1}!", Thread.CurrentThread.Name, e.Status.ToString()); System.Console.Out.Flush();
		}

		// Update crawled addresses
		Monitor.Enter(this.crawledAddressList);
		this.crawledAddressList.Add(address);
		Monitor.Exit(this.crawledAddressList);
		
		Monitor.Enter(this.threadStatus);
		this.threadStatus[Thread.CurrentThread.Name] = "";
		Monitor.Exit(this.threadStatus);

		System.Console.WriteLine("Thread <{0}> cycle done, readed {1}!", Thread.CurrentThread.Name, address); System.Console.Out.Flush();
	}
	
	// Advise the user that the thread is aborted
	System.Console.WriteLine("Thread <{0}> aborting!", Thread.CurrentThread.Name); System.Console.Out.Flush();

	// Terminate the thread
	Thread.CurrentThread.Abort();
}
premetto che funziona, nel senso che fa tutto quello che deve fare correttamente a parte che lavora un thread per volta

il mio sospetto è che sia questa riga qui

codice:
byte[] downloadedDataBytes = webClient.DownloadData(address);
quella che blocca tutto

(lasciate perdere errori o dimenticanze nel codice, molte cose sono volute perché mi interessava soltanto testare il funzionamento di una struttura di questo tipo in C# per vedere se funzionava bene o meno)

qualcuno ha qualche idea?