请考虑以下代码段,其中MyMethod
及其异步版本MyMethodAsync
以不同方式调用:
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>
}
}
}
在每种情况下,我都评论了返回类型。
问题是为什么result4
的类型也是Task<int>
?不应该是Task<Task<int>>
吗?
Task.Run
调用异步方法可能是有益的?
答案 0 :(得分:1)
它返回Task<int>
的原因是你正在调用Task.Run(Func<Task<TResult>>)
重载,它会返回一个任务,作为你的函数返回的任务的代理。如果要使用原始重载,可以指定泛型类型参数:
var result3 = Task.Run(() => MyMethod()); // Task<int>
var result4 = Task.Run(() => MyMethodAsync()); // Task<int>
var result5 = Task.Run<Task<int>>(() => MyMethodAsync()); // Task<Task<int>>
关于你的第二个问题:当异步操作使用Task.Run
时,所述操作也有一个同步部分,从而在后台线程上执行,而不是阻塞原始线程。例如,在将字符串异步写入磁盘之前,StreamWriter.WriteAsync
可能需要将字符串序列化为字节数组。序列化是同步完成的,可能会受益于在后台线程上运行。