System.Thread.Sleep(0) e’ comunemente usato quando un thread ha finito il suo lavoro e vuole rilasciare il suo “quantum” di tempo allocato, per ritornare il controllo allo scheduler ed eseguire altri threads che sono in attesa (una comune analogia e’ con Application.DoEvents).

Questa procedura pero’ non tiene conto della priorita’ assegnata ai vari threads. Se per esempio il thread che si sta eseguendo e’ l’unico con priorita’ alta, quando si chiama Sleep(0) il controllo ritorna allo scheduler che eseguira’ il prossimo thread in ordine di priorita’, che in questo caso e’ il thread stesso.

Quindi appena rilasciamo il controllo allo scheduler, il thread ritorna in coda in prima posizione e viene rieseguito immediatamente, e i threads con priorita’ bassa non vengono mai eseguiti. Oltretutto, il thread non rilascera’ piu’ la CPU, impedendo al sistema di entrare automaticamente in stand-by o suspend se necessario.

La soluzione piu’ semplice e’ di dare piu’ tempo allo scheduler per eseguire i threads con priorita’ bassa, mettendo il thread corrente in Sleep per un numero di millisecondi > 0.

La soluzione migliore, ma piu’ complessa, e’ quella di sincronizzare il thread che si mettera’ in Sleep fino a che non avra’ qualcosa da fare.

Su Windows Server 2003, lo scheduler e’ stato modificato per eseguire threads con bassa priorita’ quando Sleep(0) e’ eseguito. Ma non e’ cosi’ su altre versioni di Windows, quindi bisogna stare molto attenti quandi si usa questo metodo in threads con priorita’ alta.

References:

Sleeping vs. Yielding

Consequences of the scheduling algorithm: Sleeping doesn't always help