【问题标题】:Two Windows - one modified by thread random output两个窗口 - 一个由线程随机输出修改
【发布时间】:2018-01-15 08:23:59
【问题描述】:

我正在尝试编写代码,其中屏幕分为两个窗口,其中一个由不同的线程修改,但输出似乎非常随机。有人可以帮忙吗?上面的控制台应该由main修改,下面由线程k修改。

#include <stdio.h>
#include <ncurses.h>
#include <unistd.h>
#include <thread>
#define WIDTH 30
#define HEIGHT 10 

int startx = 0;
int starty = 0;
void kupa (int score_size, int parent_x, int parent_y)
{
    int i = 0;
    WINDOW *dupa = newwin(score_size, parent_x, parent_y - score_size, 0);
    while(true)
    {

        i++;

        mvwprintw(dupa, 0 , 0, "You chose choice %d with choice string", i);
        wrefresh(dupa);  
        sleep(5);
        wclear(dupa);
    }
    delwin(dupa);
}
int main ()
{
      int parent_x, parent_y;
      int score_size =10;
      int counter =0 ;
      initscr();
      noecho();
      curs_set(FALSE);
      getmaxyx(stdscr, parent_y, parent_x);
      WINDOW *field = newwin(parent_y - score_size, parent_x, 0, 0);
      std::thread k (kupa, score_size, parent_x, parent_y);
      while(true) {
          mvwprintw(field, 0, counter, "Field");
          wrefresh(field);
          sleep(5);
          wclear(field);
          counter++;
      }
      k.join();
      delwin(field);
}

【问题讨论】:

  • 您遇到的究竟是什么问题?错误?怎么了? “随机”是什么意思?多一点信息会非常有帮助...

标签: c++ multithreading c++11 ncurses


【解决方案1】:

底层的curses/ncurses 库不是线程安全的(例如参见What is meant by “thread-safe” code?,其中讨论了该术语)。在curses 的情况下,这意味着库的WINDOW 结构如stdscr 是不受互斥锁或其他方法保护的全局变量。该库还具有跨窗口共享的内部 静态 数据。您只能使用以下策略之一获得多线程代码的可靠结果:

  • 在一个线程内完成所有的窗口管理(包括输入)
  • 使用互斥体、信号量或任何concurrency 技术似乎最好地管理“拥有”单独窗口的单独线程。为了在这里取得成功,线程必须拥有整个屏幕,从 curses 库在等待输入时阻塞的点开始,直到它更新屏幕并继续等待输入。这比听起来更难。

ncurses 5.7 及以上版本可以编译,为reentrant code 和一些线程应用程序提供基本支持。为此,它使用围绕其静态数据的互斥锁,将全局变量变成“getter”函数,并添加显式传递许多调用中隐含的SCREEN 指针的函数。更多详情,请参阅manual page

一些 ncurses 的测试程序说明了线程支持(这些程序位于源代码的 test 子目录中):

  • 同上显示use_screen
  • test_opaque 执行 WINDOW 属性的“getter”
  • 雨秀use_window
  • 蠕虫显示use_window

【讨论】:

  • 能给我看一下 use_screen 调用函数的例子吗?
【解决方案2】:

我不确定你想做什么,但这种行为很正常。活动的线程写入窗口,当系统进行任务切换时,另一个线程写入窗口。正常行为是仅使用一个写入窗口的线程。其他线程应该只做一些工作。 无论如何,如果您使用多个线程,则必须使用事件、互斥锁、队列、信号量或其他方法来同步它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多