如何向 Console.ReadLine() 添加超时?

2023-12-12

我有一个控制台应用程序,我想在其中向用户提供x秒响应提示。如果在一段时间后没有输入,程序逻辑应该继续。我们假设超时意味着空响应。

解决这个问题最直接的方法是什么?


我惊讶地发现,5 年后,所有答案仍然存在以下一个或多个问题:

  • 使用了 ReadLine 以外的函数,导致功能丧失。 (删除/退格/向上键用于先前的输入)。
  • 多次调用时,函数会表现得很糟糕(产生多个线程、许多挂起的 ReadLine 或其他意外行为)。
  • 功能依赖于忙等待。这是一种可怕的浪费,因为等待预计会持续几秒到超时(可能长达几分钟)。运行如此长的时间的忙等待会消耗大量资源,这在多线程场景中尤其糟糕。如果用睡眠修改忙等待,这会对响应能力产生负面影响,尽管我承认这可能不是一个大问题。

我相信我的解决方案将解决原来的问题,而不会遇到上述任何问题:

class Reader {
  private static Thread inputThread;
  private static AutoResetEvent getInput, gotInput;
  private static string input;

  static Reader() {
    getInput = new AutoResetEvent(false);
    gotInput = new AutoResetEvent(false);
    inputThread = new Thread(reader);
    inputThread.IsBackground = true;
    inputThread.Start();
  }

  private static void reader() {
    while (true) {
      getInput.WaitOne();
      input = Console.ReadLine();
      gotInput.Set();
    }
  }

  // omit the parameter to read a line without a timeout
  public static string ReadLine(int timeOutMillisecs = Timeout.Infinite) {
    getInput.Set();
    bool success = gotInput.WaitOne(timeOutMillisecs);
    if (success)
      return input;
    else
      throw new TimeoutException("User did not provide input within the timelimit.");
  }
}

当然,调用非常简单:

try {
  Console.WriteLine("Please enter your name within the next 5 seconds.");
  string name = Reader.ReadLine(5000);
  Console.WriteLine("Hello, {0}!", name);
} catch (TimeoutException) {
  Console.WriteLine("Sorry, you waited too long.");
}

或者,您可以使用TryXX(out)正如 shmueli 建议的那样:

  public static bool TryReadLine(out string line, int timeOutMillisecs = Timeout.Infinite) {
    getInput.Set();
    bool success = gotInput.WaitOne(timeOutMillisecs);
    if (success)
      line = input;
    else
      line = null;
    return success;
  }

其调用方式如下:

Console.WriteLine("Please enter your name within the next 5 seconds.");
string name;
bool success = Reader.TryReadLine(out name, 5000);
if (!success)
  Console.WriteLine("Sorry, you waited too long.");
else
  Console.WriteLine("Hello, {0}!", name);

在这两种情况下,您不能混合调用Reader与正常的Console.ReadLine调用:如果Reader超时,就会出现挂起ReadLine称呼。相反,如果你想有一个正常的(非定时的)ReadLine调用,只需使用Reader并省略超时,使其默认为无限超时。

那么我提到的其他解决方案的那些问题又如何呢?

  • 可以看到,使用了ReadLine,避免了第一个问题。
  • 该函数在多次调用时行为正常。无论是否发生超时,都只会运行一个后台线程,并且最多只会有一个对 ReadLine 的调用处于活动状态。调用该函数将始终导致最新输入或超时,并且用户不必多次按 Enter 键即可提交输入。
  • 而且,显然,该函数不依赖于忙等待。相反,它使用适当的多线程技术来防止浪费资源。

我预见到这个解决方案的唯一问题是它不是线程安全的。但是,多个线程实际上无法同时请求用户输入,因此应该在调用之前进行同步Reader.ReadLine anyway.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何向 Console.ReadLine() 添加超时? 的相关文章

随机推荐

  • 使用 Freebase API 时如何从 mqlread() 获取光标?

    我正在使用 Python Freebase 模块MQLREAD 使用以下查询 query cursor True id None type games game mid None 返回 100 个条目 但结果不包括 光标 如果您手动运行查询
  • 在函数参数中用更具体的类型替换“unknown”时出错

    在我正在处理的代码库中 拥有一个包含具有类型参数的函数的通用类型是有意义的unknown 然后 无论何时使用该类型 都将函数的参数类型缩小为更具体的类型 但是 这会引发如下错误 Type unknown is not assignable
  • 一页有多个 Google Analytics 4 脚本跟踪器

    Briefly 主要想法是我有一个集成了 Google Analytics 4 GA4 的网站和一个集成到该网站中的独立小部件 该网站也具有 GA4 结果 事件被发送到两个跟踪器 我如何才能将其彼此隔离 详细的 有 2 个 React We
  • 将输入文本值作为参数传递

    我想将用户输入作为参数传递到另一个页面 这是我的代码
  • Java 正则表达式抛出 java.util.regex.PatternSyntaxException:字母 g 的转义序列非法/不受支持

    我需要查看字符串中是否存在整个单词 这就是我尝试这样做的方式 if text matches word b do something 它适用于大多数单词 但以 a 开头的单词g导致错误 Exception in thread main ja
  • Cython - 动态 2D C++ 数组的 Memoryview

    目标 使用 Cython 从 2D C 字符数组获取 Memoryview 一点背景 我有一个本机 C 库 它生成一些数据并通过char 到 Cython 世界 数组在库中的初始化和操作大约是这样的 struct Result buffer
  • 从字符串列表创建 numpy 结构化数组

    我正在开发一个 python 实用程序来从第谷 2 星目录中获取数据 我正在开发的功能之一是查询目录并返回给定明星 ID 或一组明星 ID 的所有信息 我目前正在通过循环遍历目录文件的行来执行此操作 然后尝试将行解析为 numpy 结构化数
  • jQuery 甚至没有被调用

    我不知道这里发生了什么 我正在尝试在我的菜单上添加一个滑动切换 看起来非常简单 我试图简化它以尝试找到问题 这意味着我已经采取了所有链接出来和额外的jquery 只有底部的例子 最后的段落 但我不知道错误是什么 除了它不做任何事情 包括 剧
  • ASP.Net MVC 框架和数据绑定

    我在理解 MVC 框架背后的一些概念时遇到了一些困难 我正在做一个非常简单的应用程序 对产品进行分类 创建屏幕将仅使用一个下拉列表 显示类别列表 产品名称并提交 在普通的 Net 应用程序中 我会在 Page Load 中对服务器下拉列表进
  • 如何从窗口获取像素数据\像素缓冲区并提取RGB?

    我正在窗口上绘制文本 textOut 和矩形 我想从中获取 RGB 缓冲区 我该怎么做 有 2 个选项 首先 您可以使用 GetPixel 我用过很多次 它工作正常 COLORREF GetPixel HDC hdc int nXPos i
  • 如何找到 appleid.apple.com/auth/revoke 端点所需的 client_id 和 client_secret 值?

    我想在我的项目中为通过 Apple REST API 登录的用户使用帐户删除功能 在我的 iOS 应用程序中 curl 请求中指定的 client id 和 client secret 值对应于什么值 curl v POST https a
  • jquery 验证插件 - 提交时不验证

    我有一个包含多个字段的表单 我想在键盘输入和提交时验证其中一些字段 我调用 jquery 1 9 1 然后调用插件 1 11 1 然后使用我的 js 调用外部文件 我通过 Firebug 看到它们都在加载 如果我使用下面的代码 它根本不会验
  • HTML 全屏布局,具有最小宽度、最大宽度

    我有一个项目 例如 一个 div 标签 它占据屏幕宽度的 1 3 最小宽度为 500px 最大宽度为 700px 在它旁边 还有另一个项目占据屏幕的其余部分 如果我只是指定 66 的宽度 只要其他项目的高度不采用最大值之一 它就可以正常工作
  • 阻止杰克逊将数字读取为字符串

    Jackson 将输入数字读取为字符串 作为下面的示例 Student 类将名称 4567 读取为字符串 例如 输入 name 4567 Java类 Class Student String name Jackson 正在解析 JSON 文
  • 使用 StickyGridHeaders

    粘性网格标题 但它没有按应有的方式工作 或者至少没有按我想要的方式工作 所以我得到了这个列表 里面有其他列表 然后我创建了一个标题列表 我使用原始列表 和一个完整的项目列表 所有子项目 然后像这样调用适配器 List
  • 为什么在创建 SqlClient 类型时会出现缺少方法异常运行时?

    我有以下代码 open FSharp Data
  • $_SERVER['REQUEST_URI'] 也带有 #hash 吗?

    如果我要求site page php hash the SERVER REQUEST URI 只是 page php 有没有办法在 php 没有后来的 ajax 中知道用户请求的页面 hash Thanks 简短回答 不 哈希不会传递到服务
  • Grails 使用带有 3 个以上逻辑参数的动态查找器

    我成功地使用 Hibernate 的动态查找器在数据库中进行搜索 def temp User findByNameAndStreet name street 虽然 我需要这样的三重逻辑论证 def temp User findByNameA
  • 嵌入式 Flash MP3 播放器在某些文件上速度缓慢,在其他文件上正常

    我正在使用基于 Flash 的嵌入式 MP3 播放器 独立版本WordPress 音频播放器 准确的说 在客户端的网页上播放音频 鉴于基于 Flash 的播放器的性质 AFAIK 他们都使用 Flash 的音频 视频解码库 确切的播放器产品
  • 如何向 Console.ReadLine() 添加超时?

    我有一个控制台应用程序 我想在其中向用户提供x秒响应提示 如果在一段时间后没有输入 程序逻辑应该继续 我们假设超时意味着空响应 解决这个问题最直接的方法是什么 我惊讶地发现 5 年后 所有答案仍然存在以下一个或多个问题 使用了 ReadLi