为什么在异步函数上使用Task.Run不会返回任务<task <t>&gt;

时间:2017-08-04 21:37:30

标签: asynchronous task-parallel-library return-type

请考虑以下代码段,其中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>>吗?

BTW,是否有任何情况下Task.Run调用异步方法可能是有益的?

1 个答案:

答案 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可能需要将字符串序列化为字节数组。序列化是同步完成的,可能会受益于在后台线程上运行。