C# 异步函数作为任务<int>

C# async function as Task<int>

在下面的代码中:

async static Task<int> test(){ 
    Console.WriteLine("{0}: Start 3", DateTime.Now);
    await Task.Delay(3000);
    return 3; 
}

List<Task<int>> tasks2 = new List<Task<int>> {
    test(),
    new Task<int>( delegate { Console.WriteLine("{0}: Start 3", DateTime.Now); Task.Delay(3000).Wait(); return 3; } ),
    new Task<int>( delegate { Console.WriteLine("{0}: Start 1", DateTime.Now); Task.Delay(1000).Wait(); return 1; } ),
};


foreach (var task in tasks2)
    task.Start(); // this cause exception at runtime

为什么我不能像 Task<int> 一样使用 test 方法?如果函数 returns Task<int>...

test()返回的任务在您调用test()时已经开始。所以你不能重新启动它。

实际上,test() 返回的任务是一个 promise-style 任务,它首先不在 thread-pool 线程上 运行。

您应该几乎总是创建已经开始的任务(一旦创建)。

也就是说,你不应该使用 Task 的构造函数,然后调用 Start 方法。

相反,如果您想 运行 在 thread-pool 线程上执行任务,请使用 Task.Run

正如其他人提到的,您不能调用 Start,因为它已经启动了。如果您希望这样做,您仍然可以通过检查状态来实现您的目标。请参阅下面的更新代码:

async static Task<int> test(){ 
    Console.WriteLine("{0}: Start 3", DateTime.Now);
    await Task.Delay(3000);
    return 3; 
}


        List<Task<int>> tasks2 = new List<Task<int>> {
           new Task<int>( delegate{ return test().Result;}),
            new Task<int>( delegate { Console.WriteLine("{0}: Start 3", DateTime.Now); Task.Delay(3000).Wait(); return 3; } ),
            new Task<int>( delegate { Console.WriteLine("{0}: Start 1", DateTime.Now); Task.Delay(1000).Wait(); return 1; } ),
            };

foreach (var task in tasks2)
{
        task.Start();
}

就像其他人指出的那样,当您调用 test() 时任务已经启动,因此您无法再次启动它。试试下面的代码看看发生了什么。

如您所见,每个任务都有控制台输出。 test() 返回的任务是通过调用该方法启动的。因此,此代码仅显式启动处于 Created 状态的其他任务。最后,我们通过调用 WhenAll() 等待所有任务完成,而 returns 是我们等待的任务。在打印 "All done!" 之前,您会注意到(所有任务中)最长的 3 秒延迟。

public static class AsyncTest
{
    static async Task<int> test()
    {
        Console.WriteLine("{0}: Start 3", DateTime.Now);
        await Task.Delay(3000);
        return 3;
    }

    public static void Main()
    {

        var tasks2 = new List<Task<int>>
        {
            test(),
            new Task<int>( delegate { Console.WriteLine("{0}: Start 3", DateTime.Now); Task.Delay(3000).Wait(); return 3; } ),
            new Task<int>( delegate { Console.WriteLine("{0}: Start 1", DateTime.Now); Task.Delay(1000).Wait(); return 1; } )
        };

        foreach (var task in tasks2)
        {
            if (task.Status == TaskStatus.Created)
                task.Start();
        }

        Task.WhenAll(tasks2).Wait();

        Console.WriteLine("All done!");
    }
}