O uso do tipo genérico Task<T> (namespace System.Threading.Tasks) em método assíncronos, implica invariavelmente, na alocação de recursos para a devolução de um objeto ou valor.
E se a instância a ser retornada já existir no momento em que a operação assíncrona é invocada? Ainda assim, ocorrerá a alocação de memória por conta do uso de Task<T>.
No C# 7.0, foi disponibilizada a classe ValueTask (namespace System.Threading.Tasks) como uma forma de superar essa limitação, evitando alocações desnecessárias e levando a ganhos de performance. É o que demonstra o exemplo a seguir, no qual se observa a presença do método assíncrono EsperaAleatória:
- Um valor inteiro será calculado num primeiro momento, associado ao atributo privado _tempoEsperaInicial e utilizado para um intervalo de espera (via operação Delay da classe Task);
- Execuções posteriores farão com que apenas se devolva o resultado vinculado previamente a _tempoEsperaInicial.
using System; using System.Threading.Tasks; namespace ExemploValueTask { class Program { private static int _tempoEsperaInicial; private static async ValueTask<int> EsperaAleatoria() { if (_tempoEsperaInicial == 0) { _tempoEsperaInicial = new Random().Next(5000, 10000); await Task.Delay(_tempoEsperaInicial); } return _tempoEsperaInicial; } static void Main(string[] args) { Console.WriteLine("Criando a primeira task"); var task1 = EsperaAleatoria(); Console.WriteLine("Retorno da primeira task: " + task1.Result); Console.WriteLine("Criando a segunda task"); var task2 = EsperaAleatoria(); Console.WriteLine("Retorno da segunda task: " + task2.Result); Console.ReadKey(); } } }
A execução desse conjunto de instruções produzirá um resultado similar ao seguinte conteúdo:
Referências
- New Features in C# 7.0: https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/