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!");
}
}
在下面的代码中:
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!");
}
}