2009-10-13 6 views
3

quelqu'un peut-il m'expliquer avec un exemple simple pour gérer Monitor.PulseAll(). J'ai déjà passé quelques exemples de ce stackoverflow. Comme je suis un débutant je sens que ce sont au-dessus de ma tête.Besoin d'aide dans Monitor.PulseAll()

Répondre

6

Que diriez-vous (pour montrer l'interaction):

static void Main() 
{ 
    object obj = new object(); 
    Console.WriteLine("Main thread wants the lock"); 
    lock (obj) 
    { 
     Console.WriteLine("Main thread has the lock..."); 
     ThreadPool.QueueUserWorkItem(ThreadMethod, obj); 
     Thread.Sleep(1000); 
     Console.WriteLine("Main thread about to wait..."); 
     Monitor.Wait(obj); // this releases and re-acquires the lock 
     Console.WriteLine("Main thread woke up"); 
    } 
    Console.WriteLine("Main thread has released the lock"); 
} 
static void ThreadMethod(object obj) 
{ 
    Console.WriteLine("Pool thread wants the lock"); 
    lock (obj) 
    { 
     Console.WriteLine("Pool thread has the lock"); 
     Console.WriteLine("(press return)"); 
     Console.ReadLine(); 
     Monitor.PulseAll(obj); // this signals, but doesn't release the lock 
     Console.WriteLine("Pool thread has pulsed"); 
    } 
    Console.WriteLine("Pool thread has released the lock"); 
} 

Re signalisation; lorsqu'il s'agit de Monitor (aka lock), il existe deux types de blocage; il y a la "file d'attente prête", où les threads sont mis en file d'attente en attente d'exécution. Sur la ligne après Console.WriteLine("Pool thread wants the lock");, la file d'attente de pool entre dans la file d'attente prête. Lorsque le verrou est libéré, un thread de la file d'attente prête peut acquérir le verrou.

La deuxième file d'attente concerne les threads qui doivent être éveillés; l'appel à Wait place le thread dans cette deuxième file d'attente (et libère temporairement le verrou). L'appel à PulseAll déplace tous les threads de cette deuxième file dans la file d'attente prête (Pulse ne déplace qu'un seul thread), de sorte que lorsque le thread de pool libère le verrou, le thread principal est autorisé à reprendre le verrou. Cela semble complexe (et c'est peut-être le cas) - mais ce n'est pas aussi grave que ça en a l'air ... franchement. Cependant, le code d'enfilage est toujours difficile, et doit être abordé avec prudence et une tête claire.

+0

Merci Marc.J'ai vu votre poste plusieurs.Ils sont excellents et simples à comprendre.Merci beaucoup du fond de mon cœur. – Prabugoel

+0

Marc une question.Here Signalisation signifie "Je suis sur le point de libérer"? – Prabugoel

+0

Non; mettra à jour... –

3

Monitor.Wait() attendra toujours une impulsion.

Ainsi, le principal est:

  1. En cas de doute, Monitor.Pulse()
  2. Si le doute subsiste, Monitor.PulseAll()

Autre que cela, je ne sais pas ce que vous demandez. Pourriez-vous élaborer?

Edit:
Votre disposition générale devrait être:

Monitor.Enter(lock); 

try 
{ 
    while(!done) 
    { 
     while(!ready) 
     { 
      Monitor.Wait(lock); 
     } 

     // do something, and... 

     if(weChangedState) 
     { 
      Monitor.Pulse(lock); 
     } 
    } 
} 
finally 
{ 
    Monitor.Exit(lock); 
} 
+0

Merci John.Je suis vraiment reconnaissant envers vous. :) – Prabugoel

+0

La serrure ne sera-t-elle pas automatiquement relâchée? ou avons-nous besoin de le spécifier explicitement? je veux dire Monitor.Exit (lock)? – Prabugoel

+0

@Prabugoel Si vous utilisez 'lock (obj) {}', le verrou sera automatiquement libéré. Si vous utilisez 'Monitor.Enter()', vous devez explicitement 'Monitor.Exit()'. Comment le runtime pourrait-il savoir quand libérer le verrou? 'lock (obj)' est juste un raccourci pour entrer et sortir. – bzlm