ho creato un evento di processo croce via ManualResetEvent. Quando si verifica questo evento potenzialmente n thread in n processi diversi dovrebbero essere sbloccati e iniziare a funzionare per recuperare i nuovi dati. Il problema è che sembra che ManualResetEvent.Set seguito da un Reset immediato non causi il risveglio di tutti i thread in attesa. La documentazione è piuttosto vago ciCross Process Event - Rilasciare tutti i camerieri in modo affidabile
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx
Quando lo stato di un oggetto evento manuale di reset viene segnalata, rimane segnalato finché non viene esplicitamente riportato a non segnalato dalla funzione ResetEvent . Qualsiasi numero di thread in attesa, o fili che successivamente iniziano operazioni di attesa per l'oggetto evento specificato, può essere rilasciato mentre lo stato dell'oggetto viene segnalata.
C'è un metodo chiamato PulseEvent che sembra fare esattamente ciò di cui ho bisogno ma sfortunatamente è anche difettoso.
Un thread in attesa su un oggetto di sincronizzazione può essere momentaneamente rimosso dallo stato di attesa da una modalità kernel APC, ed allora rinviato stato di attesa dopo l'APC è completa. Se la chiamata a PulseEvent si verifica durante il periodo in cui il filo è stato rimosso dallo stato di attesa , il filo non sarà rilasciato perché PulseEvent stampa solo quei thread nell'attesa al momento in cui viene chiamato. Pertanto, PulseEvent è inaffidabile e non deve essere utilizzato dai nuovi applicazioni. Invece, usa le variabili di condizione.
Ora MS consiglia di utilizzare le variabili di condizione.
variabili di condizione sono primitive di sincronizzazione che consentono discussioni attendere finché non si verifica una condizione particolare. variabili di condizione sono oggetti modalità utente che non possono essere condivise tra i processi.
In seguito ai documenti mi sembra di aver perso la fortuna di farlo in modo affidabile. C'è un modo semplice per realizzare la stessa cosa senza le limitazioni indicate con un solo ManualResetEvent o devo creare per ogni ascoltatore un evento di risposta per ottenere un ACK per ogni chiamante iscritto? In tal caso avrei bisogno di una piccola memoria condivisa per registrare i pid dei processi sottoscritti ma sembra che porti una serie di problemi. Cosa succede quando un processo si blocca o non risponde? ....
di dare qualche contesto. Ho un nuovo stato da pubblicare che tutti gli altri processi dovrebbero leggere da una posizione di memoria condivisa. Va bene perdere un aggiornamento quando si verificano più aggiornamenti contemporaneamente ma il processo deve leggere almeno l'ultimo valore aggiornato. Potrei sondare con un timeout ma non sembra una soluzione corretta.
Attualmente sto giù a
ChangeEvent = new EventWaitHandle(false, EventResetMode.ManualReset, counterName + "_Event");
ChangeEvent.Set();
Thread.Sleep(1); // increase odds to release all waiters
ChangeEvent.Reset();
Questa è un'ottima soluzione che risolve tutte le condizioni di gara che potrei trovare. Grazie! –