首页 > 解决方案 > ncurses 多线程读写的解决方法

问题描述

这就是http://invisible-island.net/ncurses/ncurses.faq.html#multithread上所说的

如果您的程序在多个线程中使用诅咒,您几乎肯定会看到奇怪的行为。这是因为 curses 依赖于输入和输出的静态变量。使用一个线程进行输入和其他线程进行输出不能解决问题,额外的屏幕更新也无济于事。此常见问题解答不是关于线程编程的教程。

具体来说,它提到即使输入和输出在不同的线程上完成也不安全。如果我们进一步为整个 ncurses 库使用互斥锁,以便一次最多可以有一个线程调用任何 ncurses 函数,是否安全?如果没有,在多线程应用程序中安全使用 ncurses 的其他廉价解决方法是什么?

我问这个问题是因为我注意到一个真正的应用程序通常有自己的事件循环,但依赖于 ncursesgetch函数来获取键盘输入。但是如果主线程在自己的事件循环中阻塞等待,那么它就没有机会调用getch. 一个看似适用的解决方案是调用getch不同的线程,这还没有给我带来问题,但正如上面所说的那样实际上并不安全,并且在这里由另一个用户验证。所以我想知道合并getch到应用程序自己的事件循环中的最佳方法是什么。

我正在考虑进行getch非阻塞并定期(每 10-100 毫秒)唤醒主线程以检查是否有要阅读的内容。但这会在关键事件之间增加额外的延迟,并降低应用程序的响应速度。另外,我不确定这是否会导致某些 ncurses 内部延迟出现任何问题,例如ESCDELAY.

我正在考虑的另一个解决方案是直接轮询标准输入。但我猜 ncurses 也应该做类似的事情,从两个不同的地方读取相同的流看起来很糟糕。

文中还提到了“ncursest”或“ncursestw”库,但它们似乎不太可用,例如,如果您使用不同的语言绑定curses。如果标准 ncurses 库有一个可行的解决方案,那就太好了。

标签: multithreadingncursescurses

解决方案


如果没有线程支持,您将无法在多个线程中使用 curses 函数。这是因为大多数 curses 调用使用静态或全局数据。getch例如调用refresh可以更新整个屏幕的函数——使用全局指针curscrstdscr. 线程支持配置的不同之处在于全局值被转换为函数并添加了互斥锁。

如果您想从不同的线程读取标准输入并在一个线程中运行curses,您可能可以通过检查文件描述符(即0)的挂起活动并警告运行 curses 的线程告诉它读取数据来完成这项工作。


推荐阅读