Dopo che l'applicazione si è bloccata, ho rintracciato la causa in un thread in attesa di un'attività creata da Task.Delay()
(o TaskEx.Delay()
in .NET 4.0) per la quale è stato fornito uno TimeSpan
calcolato che, a causa di un errore, è stato occasionalmente calcolato su TimeSpan
con un numero di TotalMilliseconds
inferiore o uguale a -1
e superiore a -2
(ovvero compreso tra -10000 e -19999 tick, inclusi).Perché Task.Delay() consente un ritardo infinito?
Sembra che quando si passa un negativo TimeSpan
che è -2
millisecondi o più bassa, il metodo genera correttamente un ArgumentOutOfRangeException
, ma quando si fornisce un periodo negativo della gamma descritta sopra, restituisce un Task
che non viene completata (impostando il sottostante System.Threading.Timer
a un dueTime
di -1 che denota l'infinito). Ciò significa che qualsiasi continuazione impostata su quell'attività non verrà mai eseguita e qualsiasi thread scadente che si verifica in .Wait()
su quello Task
verrà bloccato per sempre.
Quale possibile utilizzo può avere un Task
che non ha mai completato? Qualcuno dovrebbe aspettarsi un simile valore di ritorno? Non deve essere passato alcun valore negativo a .Delay()
, inclusi i valori in quell'intervallo speciale, un ArgumentOutOfRangeException
?
Il documento MSDN è piuttosto esplicito nel consentire -1, quindi sembra che si stia comportando correttamente. Non sono sicuro del caso d'uso per quel sovraccarico, ma potrebbe essere un modo di aspettare la cancellazione 'giusta' con il sovraccarico che richiede un token di cancellazione. –
@James: Non è esplicito nel consentire -1, è esplicito nel disabilitare valori inferiori a -1. Non dice nemmeno cosa succederà se passi -1, a differenza della documentazione di 'System.Threading.Timer'. Sembra quasi che l'elenco di eccezioni documentato sia stato generato automaticamente dal codice sorgente. E se stai aspettando la "giusta" cancellazione, perché anche chiamare a 'Task.Delay()'? –
se pensi che sia rotto, segnala un bug alla connessione. Un documento che dice "inferiore a -1 non valido" è esplicito (per me) nel dire che -1 è valido. Se l'intento era -1 come non valido "inferiore a 0 non valido" sarebbe stato più facile scrivere. Dal momento che il doc e il codice consentono entrambi -1, penso che questo sia By Design, ma sentitevi liberi di inviare un errore al collegamento (più probabile che venga elaborato dal team BCL piuttosto che un thread SO casuale, penserei :) –