Reputation: 2412
Consider the following code snippet in which the MyMethod
and its asynchronous version MyMethodAsync
is called in different ways:
using System;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static int MyMethod()
{
System.Threading.Thread.Sleep(1000);
return 42;
}
static async Task<int> MyMethodAsync()
{
await Task.Delay(1000);
return 42;
}
static void Main(string[] args)
{
var result1 = MyMethod(); // int
var result2 = MyMethodAsync(); // Task<int>
var result3 = Task.Run(() => MyMethod()); // Task<int>
var result4 = Task.Run(() => MyMethodAsync()); // Task<int>
}
}
}
In each case, I have commented the return type.
The question is why the type of result4
is Task<int>
too? Shouldn't it be Task<Task<int>>
?
BTW, is there any case that calling an async method by Task.Run
could be beneficial?
Upvotes: 1
Views: 104
Reputation: 54887
The reason it returns a Task<int>
is that you're calling the Task.Run(Func<Task<TResult>>)
overload, which returns a task that serves as a proxy for the task returned by your function. If you wanted to use the original overload, you could specify the generic type parameter:
var result3 = Task.Run(() => MyMethod()); // Task<int>
var result4 = Task.Run(() => MyMethodAsync()); // Task<int>
var result5 = Task.Run<Task<int>>(() => MyMethodAsync()); // Task<Task<int>>
As for your second question: using Task.Run
on an asynchronous operation is beneficial when the said operation also has a synchronous part, which thereby gets executed on a background thread, rather than blocking your original thread. For example, StreamWriter.WriteAsync
might need to serialize the string to a byte array before writing it asynchronously to disk. The serialization is done synchronously, and might benefit from being run on a background thread.
Upvotes: 1