Thursday 20 September 2018

Task.Run vs Task.FromResult

So it is possible that you have an interface with multiple implementations and one of the implementations is IO bound and the other is not. So in order to support both implementations, you end up creating an interface method that looks like following:

Task GetRowsAsync(int[] idList);

Let us say one implementation tries to get result by querying a SQL Server database and the other one tries to get result by querying a in-memory database.

So your database implementation might be like:

public Task GetRowsAsync(int[] idList)
{
   ... some logic
    await ExecuteQueryAsync(....); // await an async operation
    return x;
}

What about an in-memory implementation? Should you use a code like #1 or #2?

public Task GetRowsAsync(int[] idList)
{
    return Task.FromResult(x);
}

public Task GetRowsAsync(int[] idList)
{
    return await Task.Run(() => { return x; });
}

Well, let us perform an experiment.

        static async Task GetNumber()
        {
            return await Task.Run(() => { return 1000; });
        }

        static async Task GetNumber1()
        {
            return await Task.FromResult(1000);
        }

        static void Main(string[] args)
        {
            Console.WriteLine("Started");
            while(Console.ReadLine() != "quit")
            {
                Console.WriteLine(GetNumber().Result);
                Console.WriteLine(GetNumber().Result);
                Console.WriteLine(GetNumber().Result);
                Console.WriteLine(GetNumber().Result);
                Console.WriteLine(GetNumber().Result);
                Console.WriteLine(GetNumber().Result);
                Console.WriteLine(GetNumber().Result);
                Console.WriteLine(GetNumber().Result);
                Console.WriteLine(GetNumber().Result);
                Console.WriteLine(GetNumber().Result);
            }
      }

Run the code by choosing GetNumber and GetNumber method. Watch the process statistics in process explorer.

GetNumber:





GetNumber1:



Learning: Task.Run does try to schedule work even though there is nothing to wait on :).

1 comment:

  1. Thank for this explaination. Though still I lack skills when to use Task.Run or Task.fromResult.

    ReplyDelete