控制流在返回结果后如何保持在异步方法范围内?这类似于变量的闭包吗
本文关键字:类似于 变量 闭包 异步方法 结果 返回 控制流 何保持 范围内 | 更新日期: 2023-09-27 17:50:35
在下面的代码中,在"几乎完成"之前将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
出现在.Net 4.0中时没有考虑到async-await
。你仍然可以使用它,但除非你有充分的理由,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。这就是为什么您在"几乎完成">
让我们放松!你有
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);
}
编译器将其转换为以下内容:
static Task<int> AsyncCheck()
{
Task t = Task.Factory.StartNew( () =>
{
Console.WriteLine("Start awesome work");
Task d1 = Task.Delay(1000);
d1.ContinueWith(t1 => {
Console.WriteLine("Almost done");
Task t2 = Task.Delay(1000);
t2.ContinueWith( tt2 => {
Console.WriteLine("Ok, done!");
}
}
});
//no dependecies on t, so just return straight away
return Task.FromResult(42);
}
static void AsyncCall()
{
Task<int> result = AsyncCheck();
result.ContinueWith( t => {
Console.WriteLine(t.Result);
})
}
一旦任务完成,ContinueWith
将运行它的主体。这应该使控制流程清晰。