【问题标题】:asynch lambda does not producing expected result异步 lambda 不会产生预期的结果
【发布时间】:2015-02-16 04:04:12
【问题描述】:

我有这个代码:

static void Main(string[] args)
{
    Func<Task<string>> getWordAsync = async () => "hello";

    Console.WriteLine(getWordAsync());

    Console.ReadLine();
}

取自this 书。如果这不打印:

"hello"

代替:

System.Threading.Tasks.Task`1[System.String]

【问题讨论】:

  • lambda 按预期工作。 async lambda的返回值是一个封装了异步操作的Task

标签: c# .net lambda async-await c#-5.0


【解决方案1】:

不要往幕后看!

async/await 关键字实际上并不是公共语言规范(CLR 所基于)的一部分,而是编译器的产物。编译器将您的 lambda 重写为不返回字符串,但实际上返回 Task&lt;string&gt;。您应该能够清楚地看到这一点,因为

() => "hello" 

是一个Func&lt;string&gt;,它在执行时返回一个 System.String,而你的变量是类型

Func<Task<string>>

或者,一个Func&lt;T&gt;,在执行时返回一个Task&lt;string&gt;

所以,当你执行 func 时,返回结果是一个

System.Threading.Tasks.Task`1[System.String]

(Task`1[System.String] 是泛型类型如何输出其泛型参数的示例)

所以,这条线

Console.WriteLine(getWordAsync());

正在对Task&lt;string&gt; 类型的对象调用ToString(),它会打印出类型的名称。这是意料之中的。

任务实际上在不同的线程上运行,因此您需要执行以下操作之一来获取任务的结果:

Console.WriteLine(await getWordAsync());

(在使用此版本之前,您必须将 Main 方法标记为 async)或

Console.WriteLine(getWordAsync().Result);

第二个会阻塞当前线程,直到结果可用。当结果可用时,第一个将在不同的线程上执行 Console 方法。顺便说一句,这是 async/await 兔子洞的又一步。

【讨论】:

  • 非常感谢。我知道在这种情况下,回报是不同的。 .Result 是有道理的,所以等待 Console.WriteLine 的一部分也是有道理的——谢谢!!!
  • 顺便说一句,用异步标记入口点(主)不起作用,Console.WriteLine(await getWordAsync());
  • 入口点(main)不能标记为async;将示例移到一个新类中并用async 标记该方法,它将按照Will 的描述工作。
  • @csetzkorn 好的,所以也许编译器不喜欢重写入口点。因此,将除 ReadLine 调用之外的所有代码移至不同的 static async void 方法。从您的 Main 方法中调用它。 (不要在 Main 方法中使用 await 关键字)
【解决方案2】:

要获得async 函数的结果,您需要使用await 关键字。另一种选择是获取Task 对象的Result 属性。

【讨论】:

  • 谢谢。是的,resharper 抱怨过这个,但我在哪里等待。尝试了几个选项。
  • 我在阅读时正在尝试 - 很抱歉提出问题......我在发布这篇文章之前尝试了等待。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多