【问题标题】:await Console.ReadLine()等待 Console.ReadLine()
【发布时间】:2021-05-11 05:08:42
【问题描述】:

我目前正在构建一个异步控制台应用程序,我在其中创建了类来处理应用程序的不同区域。

我创建了一个 InputHandler 类,我设想它会等待 Console.ReadLine() 输入。但是,您不能等待这样的功能(因为它不是异步的),我目前的解决方案是:

private async Task<string> GetInputAsync() {
    return Task.Run(() => Console.ReadLine())
}

运行良好。但是,我的(有限)理解是调用 Task.Run 将触发一个新的(并行?)线程。这违背了异步方法的目的,因为新线程现在被阻塞,直到 Readline() 返回对吗?

我知道线程是一种昂贵的资源,所以我觉得这样做真的很浪费而且很笨拙。我也试过 Console.In.ReadLineAsync() 但它显然是错误的? (好像挂了)。

【问题讨论】:

  • 嗯,不,它不会破坏异步方法的目的。这是不阻止来电者。这当然需要一个线程,Console.ReadLine() 是一个阻塞调用。
  • 线程不一定是昂贵的资源,只要你不走得太远,或者更确切地说,有时以某种方式需要它们。如果您的控制台应用程序在等待 Console.ReadLine() 时正在后台处理某些内容,那么这是一个好主意。
  • 那不是return await Task.Run( ( ) =&gt; Console.ReadLine( ) );吗?我尝试了你写的方式,但是编译器出错了……

标签: c# asynchronous console async-await


【解决方案1】:

我知道线程是一种昂贵的资源,所以我觉得这样做真的很浪费而且很笨拙。我也试过 Console.In.ReadLineAsync() 但它显然是错误的? (好像挂了)。

不幸的是,控制台流确实有令人惊讶的行为。根本原因是它们阻塞以确保控制台流的线程安全。我个人认为在异步方法中阻塞是一个糟糕的设计选择,但微软决定这样做(仅适用于控制台流)和have stuck by their decision

因此,如果您确实想要真正异步读取,此 API 设计强制您使用后台线程(例如,Task.Run)。这不是您通常应该使用的模式,但在这种情况下(控制台流),绕过他们的 API 是一种可接受的 hack。

但是,我的(有限)理解是调用 Task.Run 将触发一个新的(并行?)线程。

不完全是。 Task.Run 会将一些工作排​​队到线程池中,其中一个线程将执行代码。线程池根据需要管理线程的创建,您通常不必担心它。所以,Task.Run 并不像每次都创建一个新线程那样浪费。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-29
    • 2013-12-02
    • 2018-12-09
    • 1970-01-01
    • 2018-05-04
    • 2020-05-09
    • 2021-09-15
    • 1970-01-01
    相关资源
    最近更新 更多