c# - 返回结果后,控制流如何保留在异步方法范围内?这类似于变量的闭包吗?

标签 c# .net async-await task-parallel-library

在下面的代码中,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.StartNewasync-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/

相关文章:

c# - 是否可以在创建 Autofac LifetimeScope 后向其添加注册?

c# - 如何从 RichTextBox 中的光标位置选择前一个字符

c# - String.StartsWith 在下一个字符是素数符号时不起作用 (char)697

javascript - 使用await作为参数

c# - 为什么 async await 会抛出 NullReferenceException?

c# - 对列表进行分组并对结果匹配项执行功能

c# - 如何获取 Entity Framework 中的特定列

c# - 远程方法调用的 .NET 标准是什么?

c# - Entity Framework Designer 首先获取导航属性作为任务

rust - 我可以在 Rocket 中使用 async fn 作为处理程序吗?