0

I am using a WebClient to upload a string an retreive the answer from the server. To get the job done quicker, I decided to use the ThreadPool, but I need to know when all the downloads are over.

So far, I've been using a CountdownEvent which is supposed to decrease when the server's answer has been processed.

My main thread executes this :

CountdownEvent cde = new CountdownEvent(retour["contenu"].Count()); //Set the countdown with the number of Thread that needs to be created

foreach (var tab in retour["contenu"])
{
    App.AnniversaryViewModel.Items.Add(new Utilisateur(int.Parse((string)tab["id"])));
    System.Diagnostics.Debug.WriteLine("Création d'un utilisateur avec l'id : " + (string)tab["id"]);
    //System.Diagnostics.Debug.WriteLine("Le dernier utilisateur est : " + Items.Last<Utilisateur>().NOMPrenom);
    ThreadPool.QueueUserWorkItem(App.AnniversaryViewModel.Items.Last<Utilisateur>().telechargerLesInfos , cde); //Starts the download

}
//Waiting for every Thread to be done

cde.Wait();

System.Diagnostics.Debug.WriteLine("On a fini d'attendre");

And here is, in another class, the code that is supposed to be executed by each thread :

public void telechargerLesInfos(Object cde)
{

    APIWebTeam.sendRequest(RequestType.PROFIL, (Newtonsoft.Json.Linq.JObject reponse) =>
    {
        processInfos(reponse); //Takes the answer from the server and parse it to fill private fields
        ((CountdownEvent)cde).Signal();
    }, "&idProfil=" + id);

}

The thing is that the delegate refuses to execute, as if the "cde.Wait()" is also forcing the thread handling the delegate to wait. How can I fix / avoid that?

grumlu
  • 25
  • 1
  • 1
  • 3

1 Answers1

2

First off, the thread pool isn't really doing anything here. You're only starting an asynchronous operation in the thread pool. Starting such an operation takes basically no time at all. You may as well just do it in the main thread.

As for why the main thread is being blocked; that's easy, you're blocking the main thread yourself by waiting on the countdown event.

There is no way to have the main thread block until the async operation completes without blocking the main thread. They're literally contradictory requirements.

Instead you need to make your entire program asynchronous, to avoid blocking the main thread. Have this method take a callback that it should execute when the async operation completes, for example. The other option is to use the Task Parallel Library. Tasks make working with asynchronous operations quite a lot easier, especially if you're in a position to leverage the await keyword.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • I am not sure I understand well how to do it: am I supposed to make the telechargerLesInfos method async? – grumlu Dec 23 '13 at 16:42
  • @grumlu There are any number of ways to go about solving the problem. You need to make the method be properly asynchronous. Using the `async` keyword is one possible avenue of doing that; probably the easiest option, but not the only option. There are ways of making a method asynchronous using callbacks, or using tasks without the `async` keyword, using events, etc. – Servy Dec 23 '13 at 16:44
  • I see what you mean, what I still don't understand is why the callback in APIWebTeam.sendRequest isn't executed (is it supposed to be executed in the main thread? is it that method that should be asynchronous?) – grumlu Dec 23 '13 at 16:49
  • @grumlu If the callback is trying to invoke into the main thread then you're deadlocking; it's waiting on the main thread while the main thread is waiting on it. If you want to use asynchronous code then basically everything needs to be asynchronous, in that nothing is ever waiting on any long running operation, but instead is always scheduling callbacks that will fire whenever those long running operations finish. – Servy Dec 23 '13 at 16:54