C#: Using Task.FromResult() to wrap a value when there is no Task

c.pngTask.FromResult() creates a finished Task that holds a value in its Result property. It allows you to create a pre-computed task.

What good is that? Imagine you have been told that you need to create a class that implements this simple Interface:

public interface IEquity
{
    Task<string> GetEquityTask(string id);
}

Most of the time your implementation will get the Equity from a fast cache but the return value of the Interface is a Task and your cache doesn’t return Tasks, it returns an Equity.  You can wrap the Equity in a Task with Task.FromResult:

public class Equity : IEquity
{
    public Task<string> GetEquityTask(string id)
    {
        //Get the Equity from cache
        var equityFromCache = GetEquityFromCache(id);
 
        //If the Equity is found return it wrapped in a Task 
        //to fulfull the interface
        if (!string.IsNullOrWhiteSpace(equityFromCache))
        {
            //Wrap the Equity in a Task
            return Task.FromResult<string>(equityFromCache);
        }
 
        //No cache hit? Ok, then go get a Task which will get the Equity
        //from a slow backend.
        return Task.Run<string>(async () =>
        {
            var equity= await GetEquityFromDatabaseAsync(id);
            AddEquityToCache(id,equity);
            return equity;
        });
      
    }

……

}

To use this now, we can simple wrap a bunch of Tasks into a Task.WhenAll()

class Program
{
    static void Main(string[] args)
    {
        var ids = new[] {"A1""A2""A3"};
        var tasks = from id in ids
            select new Equity().GetEquityTask(id);
        Task.WhenAll(tasks).ContinueWith(equities=>
        {
            foreach (var equity in equities.Result)
            {
                Console.WriteLine(equity);
            }
        }).Wait();
    }
}

 

Advertisements