2009-04-10 7 views
0

Supposons que ThreadA et ThreadB appellent tous deux WaitOne() dans cet ordre sur le même AutoResetEvent. Lorsque l'événement est défini, pourquoi ThreadB est-il libéré au lieu de ThreadA?Pourquoi le deuxième thread est-il publié avant le premier, quand ils ont tous deux appelé WaitOne() et ont été libérés par un AutoResetEvent?

J'ai couru un test pour savoir ce qui se passe lorsque vous définissez un AutoResetEvent sur lequel mutiple threads attendent:

private static void Test() 
    { 
     // two threads - waiting for the same autoreset event 
     // start it unset i.e. closed i.e. anything calling WaitOne() will block 
     AutoResetEvent autoEvent = new AutoResetEvent(false); 

     Thread thread1 = new Thread(new ThreadStart(WriteSomeMessageToTheConsole)); 
     thread1.Start(); // this will now block until we set the event 

     Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole)); 
     thread2.Start(); // this will now also block until we set the event 

     // simulate some other stuff 
     Console.WriteLine("Doing stuff..."); 
     Thread.Sleep(5000); 
     Console.WriteLine("Stuff done."); 

     // set the event - I thought this would mean both waiting threads are allowed to continue 
     // BUT thread2 runs and thread1 stays blocked indefinitely 
     // So I guess I was wrong and that Set only releases one thread in WaitOne()? 
     // And why thread2 first? 
     autoEvent1.Set(); 
    } 

Le code est bien sûr pas utile; c'est juste un exemple de souris mickey. Et ce n'est pas important/urgent. Mais je serais intéressé à en savoir plus quand même ...

+0

Essayez d'appeler autoEvent1.Set(); encore une fois pour voir si l'autre thread sera libéré. Je pense que vous devez tourner l'interrupteur deux fois. –

+0

Salut - oui J'ai essayé tout de suite après - je peux obtenir le deuxième fil pour continuer avec un second appel à Set() - mais seulement si j'introduis un délai par exemple. avec un appel à Thread.Sleep(). –

+0

Je suis actuellement plus intéressé de voir si quelqu'un sait réellement que le fil qui est libéré est aléatoire. La documentation indique que les threads sont mis en file d'attente en indiquant une sorte d'ordre (c'est pourquoi je m'attendais à ce que le premier thread soit publié en premier). –

Répondre

2

IIRC, thread qui est libéré par un événement de réinitialisation automatique est non spécifiée. Comme tout le monde dit d'autre, vous voulez un événement de réinitialisation manuelle si vous souhaitez diffuser une condition. Si vous voulez libérer un nombre exact (disons exactement 3 de n), alors vous voudrez probablement utiliser un sémaphore

Si vous voulez vraiment comprendre pourquoi la commande pourrait être différente de ce que vous attendez, jetez un oeil à "Windows Internals" ou quoi que ce soit que Mark Russinovich a écrit. il y a des chances qu'il explique l'ordre d'attente sur les ressources exécutives quelque part.

0

Sur un AutoResetEvent, Set ne libère un fil. Vous devez utiliser un ManualResetEvent pour libérer plusieurs threads en attente.

+0

OK - merci pour la confirmation - aucune idée pourquoi le deuxième thread est libéré en premier? Est-ce juste le hasard que cela semble toujours être le cas ou est-ce toujours le dernier thread appelant WaitOne() qui sera libéré (et les autres doivent attendre un autre appel à Set()?) –

+0

Je suppose que ce n'est pas comme ça utilisez-le btw :). Je suis toujours curieux cependant. –

+0

Je pense que c'est juste un hasard. –

1

De MSDN

MSDN sur ManualResetEvent:. « Threads qui appellent WaitOne sur le ManualResetEvent bloque, en attente d' le signal Lorsque le fil contrôle complète l'activité, il appels réglés pour vous signaler les threads en attente peuvent continuer. Tous les threads en attente sont libérés.

Mais pour AutoResetEvent, MSD N dit: « Appel Set signaux AutoResetEvent à sortie un fil d'attente. AutoResetEvent reste signalé jusqu'à ce que un thread d'attente unique soit libéré, puis automatiquement revient à l'état non signé. Si pas de fils en attente, l'état reste indéfiniment signalé.

"

Questions connexes