2009-02-19 14 views
9

Sto lavorando su un'applicazione server client. In determinati momenti, su determinate macchine, quando ci sono più di 5 client che richiedono dati, sembra raggiungere un punto morto. Se passo a eseguire il debug del problema, il programma sembra essere in fase di elaborazione. Semplicemente impostando un punto di interruzione in cui so che il programma è in esecuzione, e facendo in modo che colpisca il punto di interruzione un paio di volte lo fa terminare. Se inserisco Thread.Sleep (0) in determinati punti del codice, principalmente attorno ad alcuni cicli intensivi della cpu, sembra che risolva quasi completamente il problema. L'unico problema che ho ora è che se chiamo Thread.Sleep (0) troppo, può rallentare il codice. Se non lo chiamo abbastanza, il codice sembra essere in stallo. Anche se posso verificare che non è in deadlock perché se inserisco il codice, il problema scompare, semplicemente perché sto mettendo in pausa un thread.Perché Thread.Sleep (0) risolve i miei problemi e come evitarlo?

C'è un buon modo per rintracciare esattamente ciò che sta causando questo. Sembra che accada solo sul mio portatile che esegue Vista, ma non sul mio desktop che esegue Windows XP. Tuttavia, è impossibile eseguire il debug, poiché il semplice passaggio nel codice fa sì che il problema si risolva. Ho letto i commenti che chiamare Thread.Sleep (0) è una cattiva pratica, e non dovrebbe essere necessario, e non mi piace inserire il codice di tipo witchcraft nelle mie applicazioni che non capisco perché debba essere lì . Qualsiasi suggerimento sarebbe molto apprezzato.

[EDIT] Posso anche verificare che il codice è ancora in esecuzione quando è "in stallo", perché se lo lascio abbastanza a lungo, finirà, solo la quantità di tempo necessario è di molti ordini di grandezza superiore. Voglio dire che in realtà è almeno 100 volte più lento quando è in questa modalità "deadlocked". La CPU è ancorata all'80-95%, quindi funziona, anche se ciò che sta facendo è oltre me, perché ci vuole sempre un tempo per completare l'operazione.

[Maggiori informazioni] Solo perché tutti qui insistono sul fatto che si tratta di una situazione di stallo, ho rimosso tutto il codice che ha causato il blocco. C'erano solo un paio di linee di codice che facevano qualsiasi tipo di blocco. I thread funzionano completamente in modo indipendente per la maggior parte, quindi non è stato molto lavoro per rimuovere completamente il blocco. Ancora il problema persiste. Non ci sono più synclock nel mio codice, non più mutex non più roba che vedo vedere che causerebbe un deadlock, ma il problema è ancora lì. E non è bloccato. Funziona, anche se molto lentamente, anche se sta consumando tutte le risorse del processore.

+0

Potresti pubblicare il codice? – Shawn

+0

Scusate, un sacco di codice da pubblicare, e non mi sembra qualcosa che potrei ricreare con un po 'di codice. – Kibbee

+0

La macchina che presenta il problema della mutli-CPU e quella che non ha una CPU singola? Ciò può esporre molti problemi di conflitto di risorse multi-thread. – zdan

risposta

1

Provare a stampare una linea ogni volta che si blocca un mutex e si stampa un'altra linea quando lo si sblocca. Ricordati di includere il nome della funzione e l'ID del filo quando lo stampi. Dovresti darti un'idea di quando sta chiudendo. Sembra una condizione di competizione che chiama sleep (0) fa sì che la CPU usi i cicli che elaborano la chiamata alla funzione. Quindi causando un sonno inerente.

11

Thread. Il sonno (0) è una resa. Sto indovinando questo riorganizza il modo in cui si chiama per evitare alcuni problemi. Penso che se avessi rilasciato il codice con il rendimento e lo avessi eseguito su 1000 macchine, avresti ricevuto molte segnalazioni di bug. Sto indovinando che hai bisogno di un tipo di blocco/sezione critica per evitare il blocco morto perché alcuni in cui il codice non è thread-safe. Potrebbe essere in una libreria che stai chiamando.

  1. Aggiungere la registrazione e verificare se i problemi si verificano ancora. Speriamo che tu possa capire quali funzioni stanno causando il blocco guasto
  2. Aggiungere alcune sezioni critiche. Utilizza un approccio divide et impera che dovrebbe essere in grado di restringere il punto in cui il problema sta accadendo.
+4

In altre parole, 'Sleep (0)' sta probabilmente mascherando una condizione di competizione. – SamB

4

È impossibile rispondere senza guardare l'intero codice base.

Chiamata discussione.Il sonno è un esercizio ORRIBILE e non dovresti farlo. Stai sostanzialmente spostando i tempi del tuo codice che sta portando allo stallo, invece di affrontare effettivamente la condizione di deadlock per cominciare.

Il motivo per cui il debug non mostra il problema è che quando il debugger si interrompe, tutti i thread nel codice si fermano, in modo da distorcere anche i tempi dell'esecuzione del programma.

Quello che si vuole fare qui è inserire il codice di registrazione qui per tracciare il percorso di esecuzione del codice su diversi thread e, in base a ciò, determinare dove si trova il deadlock.

1

Penso che sia tempo per te di allontanarti dal computer e fino alla lavagna. Analizza in che modo ogni elemento si blocca e in quali condizioni rilascia il blocco con attenzione. Cinque thread potrebbero essere un problema difficile, quindi forse vedere se solo due thread possono causare la stessa condizione. Qualcosa non si blocca correttamente e devi trovare dove.

A meno che il tuo codice non valga questo sforzo, lascia lì il Thread.sleep(), perché in realtà non fa molto male alla tua performance nel grande schema delle cose.

3

Cosa c'è all'interno di questo? Problemi simili possono apparire se si verificherà qualche campo in un ciclo per sincronizzare più thread:

while (_field); // waiting for _field change in another thread 

Questa soluzione funziona molto lento e chiama a Thread.Sleep (0) non è una soluzione, ma può essere un hack in alcuni casi. Questo può essere risolto correttamente se si modifica il ciclo di sincronizzazione chiamando al metodo WaitHandle.WaitOne() di un oggetto di sincronizzazione (ad esempio ManualResetEvent) e posizionando un segnale su questo handle in un altro thread. Forse il tuo problema è qualcosa del genere? Si prega di fornire parte del codice.

1

È sicuramente necessario avere problemi di threading che devono essere risolti. Chiamare thread.Sleep (0) fa in modo che lo scheduler si avvii. Questo probabilmente dà ad ogni thread un'opportunità di funzionare abbastanza per far funzionare le cose. Non vorrei lasciare il sonno lì dentro e lasciarlo perché quelli sono il tipo di cose che funzionano per un po 'e poi un cambiamento totalmente non correlato finisce per rompere le cose.

1

A meno che l'hardware non ti costringa, non devi mai usare sleep().

Prova a pensare al problema in un modo diverso. Considera quali dati devono essere condivisi tra i thread e pensa ai modi per inviare i dati (IE, copiali) alle parti interessate invece di condividere l'accesso .. Se fai bene, potresti non aver bisogno di alcun mutex ...

Ricordate, le variabili locali esistono su diversi stack, ma le statistiche all'interno delle funzioni sono essenzialmente globali (e, naturalmente, è necessario osservare da vicino le vostre globali).

+0

Non dovresti mai usare il sonno? Sleep (0) è utile per cose come i loop di gioco in cui si desidera utilizzare quanto più processore possibile, senza bloccare altri processi di sistema. – FryGuy

0

Forse provare a utilizzare uno strumento come Typemock Racer?

Disclaimer: Non ho mai usato questo strumento prima.

2

Quanti thread simultanei sono in esecuzione quando si blocca? Se si hanno troppi thread, la CPU potrebbe passare tutto il suo tempo facendo il cambio di contesto. Inoltre, si dovrebbe masticare attraverso 1 + MB di memoria per thread.

0

Sì, è possibile che si sia verificato un sovraccarico del programma di pianificazione.

Spero sinceramente di no.

Problemi correlati