在下面的代码中,42 在“几乎完成”之前打印到控制台。既然已经返回了42,怎么控件还在AsyncCheck
中呢?我知道如果任务在“等待”时尚未完成,它将返回控制权,但这里我有一个明确的返回语句,所以我在解决这个问题时遇到了一些麻烦。
async static Task<int> AsyncCheck()
{
await Task.Factory.StartNew( async () =>
{
Console.WriteLine("Start awesome work");
await Task.Delay(1000);
Console.WriteLine("Almost done");
await Task.Delay(1000);
Console.WriteLine("Ok, done!");
});
return 42;
}
async static void AsyncCall()
{
int result = await AsyncCheck();
Console.WriteLine(result);
}
我正在使用“async void”来检查这个示例。
最佳答案
你不应该使用 Task.Factory.StartNew
与 async-await
.你应该使用 Task.Run
. Task.Factory.StartNew
没有async-await
进入.Net 4.0心里。您仍然可以使用它,但除非您有充分的理由,Task.Run
是更安全的选择。
而不是返回 Task
它返回 Task<Task>
您需要在等待之前解包:
Task<Task> task = Task.Factory.StartNew( async () =>
{
Console.WriteLine("Start awesome work");
await Task.Delay(1000);
Console.WriteLine("Almost done");
await Task.Delay(1000);
Console.WriteLine("Ok, done!");
});
Task unwrappedTask = task.Unwrap();
await unwrappedTask
没有它,您就不会真正等待 lambda 完成。你所做的只是使用 ThreadPool
线程来启动这个异步方法。
基本上,您是在代码流继续进行的同时在不同的线程上并行执行 lambda。这就是为什么您在“几乎完成”之前看到“42”
关于c# - 返回结果后,控制流如何保留在异步方法范围内?这类似于变量的闭包吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30415729/