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/





