O Task.Delay é verdadeiramente assíncrono como uma operação de E / S, ou seja, ele depende de hardware e interrupções em vez de um thread?

Dec 09 2020

Eu encontrei uma tonelada de conteúdo relacionado que rodeia o arbusto e nunca fui capaz de encontrar uma resposta. Tenho quase 100% de certeza de que Task.Delay(int)não usa thread, pois posso executar esse código na minha máquina com apenas 16 processadores lógicos:

var tasks = new List<Task>();
for(int i = 1; i < 100000; i++) tasks.Add(Task.Delay(10000));
await Task.WhenAll(tasks);

E leva dez segundos para ser concluído. Se estivesse usando cerca de cem mil fios, demoraria um pouco mais, eu acho.

Então, minha pergunta é como Task.Delay(int)funciona? Não da maneira que esta pergunta SO mal intitulada indica, mas do ponto de vista de recursos de hardware e threading.

Respostas

4 StephenCleary Dec 11 2020 at 12:24

Na implementação atual do .NET, há um único "encadeamento de cronômetro" que apenas rastreia as instâncias de cronômetro gerenciado e gera seus eventos nos momentos apropriados. Este encadeamento do temporizador será bloqueado em seu sinal de controle com um tempo limite definido para o próximo tempo de vencimento do temporizador. O sinal de controle é usado para adicionar / remover / alterar temporizadores, portanto, quando essa solicitação de bloqueio atinge o tempo limite, o thread do temporizador sabe que o próximo temporizador foi acionado. Esta é uma operação normal de bloqueio de thread, portanto, internamente, o thread é inativo e removido da fila do planejador até que a operação de bloqueio seja concluída ou expirar. O tempo limite dessas operações é controlado pela interrupção do cronômetro do agendador do sistema operacional.

Então, tecnicamente, há um thread, mas é apenas um thread por processo, não um thread por Task.Delay.

Mais uma vez, enfatizo que isso está na implementação atual do .NET. Outras soluções foram propostas, como um encadeamento de cronômetro por CPU ou um pool dinâmico de encadeamentos de cronômetro. Talvez eles tenham sido experimentados e rejeitados por algum motivo, ou talvez uma solução alternativa seja adotada no futuro. AFAIK isso não está oficialmente documentado em nenhum lugar, então este é um detalhe de implementação.