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?
Run the code by choosing GetNumber and GetNumber method. Watch the process statistics in process explorer.
Task
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
{
... 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);
}
}
GetNumber:
GetNumber1:
Learning: Task.Run does try to schedule work even though there is nothing to wait on :).
Thank for this explaination. Though still I lack skills when to use Task.Run or Task.fromResult.
ReplyDelete