Domanda

Ho un po 'di codice, che non riesco a capire correttamente. Il problema è che il programma è multithread e all'interno c'è un po 'di codice che dovrebbe essere sincronizzato, quindi ho scritto questo:

lock (lockObject)
{
   if (!Monitor.TryEnter(lockObject))
     Monitor.Wait(lockObject);

   //do stuff...
   Monitor.PulseAll(lockObject);
}
Monitor.Exit(lockObject);

il problema che ho è che in un certo momento tutti i thread sembrano dormire - qualcuno può dire perché? Il programma continua a funzionare all'infinito consumando quasi nessun CPU, ma non viene fatto alcun lavoro - quando ho rintracciato il programma ho scoperto che ad un certo punto nessun thread è attivo ma molti di loro stanno dormendo. So che l'errore principalmente (nel caso di uno sviluppatore - sempre) si trova 0,5 m davanti al monitor - ma non riesco a capirlo da solo ... forse in pochi minuti;)

qualcuno può spiegarmelo, grazie in anticipo.

È stato utile?

Soluzione

C'è una differenza tra LockObject e lockObject ? Non è chiaro ...

Tuttavia! Se sono oggetti diversi, prima di tutto: non puoi Wait su un lucchetto che non hai ... e TryEnter restituirà false solo se specifichi un tempo scaduto. Che cosa sta esattamente cercando di fare quel codice?

Senza più contesto, non è del tutto chiaro cosa siano progettati per fare PulseAll e Wait ; ad esempio, qui vengono utilizzati per bloccare la coda quando è troppo pieno ( Wait ) o rilascialo quando lo spazio diventa disponibile ( PulseAll ), ecc. È difficile eseguire il debug del codice di threading senza le interazioni complete tra thread.

Sembra che potresti semplicemente aver bisogno:

lock (lockObject)
{
    // do stuff
}

Ci sono due problemi immediati che posso vedere; in primo luogo, non è ovvio che rilasci sempre i blocchi che prendi (cioè le eccezioni). Prova a usare lock per Enter / Exit - funzionerà correttamente.

In secondo luogo; se tutti i thread chiamano Wait ... chi li sveglierà? Cosa stanno aspettando ? Come presentato: sì, dormiranno tutti indefinitamente.

Altri suggerimenti

Sto supponendo che la prima istruzione di blocco sia un refuso e intendevi lock (lockObject) (lettere minuscole).

Penso che tu abbia frainteso le serrature un po 'qui. Il blocco if nel tuo codice non sarà mai vero. Il motivo è che quel lock (lockObject) si estende effettivamente al seguente

Monitor.Enter(lockObject);
try {
...
} finally{ 
Monitor.Exit(lockObject);

Quindi quando premi il blocco if possiedi già il blocco e TryEnter dovrebbe sempre riuscire.

Questa è una strana configurazione. "LockObject" è uguale a "lockObject"? O è un errore di battitura? Se sono uguali, la configurazione è ridondante, in quanto non è necessario chiamare Monitor.Prova Inserire qualcosa che si sta già bloccando. Se "LockObject" è un oggetto diverso, perché non spostare Monitor.Exit all'interno dell'istruzione lock?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top