为什么下面的程序永远不会结束?
namespace Example
{
class Program
{
static async Task Main(string[] args)
{
var result = await new Program().test();
Console.WriteLine(result);
}
private async Task<(int, string)> test()
{
var result = new Task<(int, string)>(() => (10, "sssss"));
return (result.Result.Item1, result.Result.Item2);
}
}
}
我注意到的是,result.Result
或写 await new Task<(int, string)>(() => (10, "sssss"));
会让程序永远等待!!
答案 0 :(得分:4)
Task
构造函数创建一个“冷”任务,一个尚未启动的任务。如果您 await
这样的任务,await
将永远不会完成,因为该任务将永远处于 Created
状态,并且永远不会转换到 RanToCompletion
状态。要启动冷创建的任务,您必须调用其 Start
或 RunSynchronously
方法,最好将 TaskScheduler.Default
作为参数传递:
private Task<(int, string)> TestAsync()
{
var task = new Task<(int, string)>(() => (10, "sssss"));
task.Start(TaskScheduler.Default);
return task;
}
使用 Task
构造函数创建冷任务是一种在实践中很少使用的高级技术。创建 delegate-based tasks 的常用方法是使用静态 Task.Run
方法,该方法创建热点任务。下面的方法在功能上与之前的方法相同¹:
private Task<(int, string)> TestAsync()
{
return Task.Run(() => (10, "sssss"));
}
请注意,以上两种方法都被认为是不好的做法,原因解释了here。
¹ 实际上并不完全相同。第二个示例启动具有 TaskCreationOptions.DenyChildAttach
配置的任务。可以在 here 中找到有关这方面的更多信息。
答案 1 :(得分:3)
混合使用 async await
和阻塞调用如 .Result
会导致死锁
如果没有异步,则无需等待。只需用您想要的值返回 Task.FromResult
private Task<(int, string)> test() {
(int, string) value = (10, "sssss");
return Task.FromResult(value);
}
它将返回一个成功完成的具有指定结果的任务。