Как извлечь данные из блокировки чтения в другом потоке в Gtk3? - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть библиотека, которая только предоставляет функцию блокировки чтения потоковых данных.Теперь мне нужно прочитать данные и показать в GTK3 GUI.Поэтому я использовал канал транзакции для передачи данных из потока, выполняющего чтение, в поток GUI, а затем считал переменную через g_idle_add.Видимо, это неправильно.Приложение вызвало занятость процессора.Как правильно?

Псудо-код:

idleAdd PRIORITY_DEFAULT_IDLE $ do
  readTChan chan >>= \case
    Nothing -> return SOURCE_CONTINUE
    Just data -> show_data_in_textview data
forkIO $ loop $ do
  theRead >>= writeTChan chan

1 Ответ

0 голосов
/ 24 сентября 2018

Использование IOChannel с трубой :

#include <gtkmm.h>
#include <string>
#include <iostream>
#include <thread>
#include <chrono>
#include <fcntl.h>
using namespace std::chrono_literals;

int main(int argc, char* argv[])
{
    auto Application = Gtk::Application::create();
    Gtk::Window window;
    Gtk::ScrolledWindow scrolled;
    Gtk::Box box(Gtk::ORIENTATION_VERTICAL) ;

    window.add(scrolled);
    scrolled.add(box);
    window.show_all();

    int pipeDescriptors[2];
    pipe(pipeDescriptors);
    bool keepAlive = true;
    auto channel = Glib::IOChannel::create_from_fd(pipeDescriptors[0]);
    channel->set_flags(Glib::IO_FLAG_NONBLOCK| Glib::IO_FLAG_IS_READABLE);
    Glib::signal_io().connect([&](Glib::IOCondition ioCondition)->bool
    {
        std::cerr<<"condition: "<<ioCondition<<std::endl;
        Glib::ustring fifoData;
        channel->read_line(fifoData);
        std::cerr<<"read: "<<fifoData<<std::endl;
        auto label = new Gtk::Label(fifoData);
        box.add(*label);
        box.show_all();
        return true;
    }, channel, Glib::IO_IN);

    auto thread = std::thread([&]{
        while(keepAlive)
        {
            std::string buffer = "theRead()\n";
            //it can also be char*. Newline is important because of read_line in the handler

            write(pipeDescriptors[1], buffer.c_str(), buffer.size());
            std::this_thread::sleep_for(1s);
        }
    });

    window.signal_delete_event().connect([&](GdkEventAny* any_event)->bool{
        keepAlive=false;
        thread.join();
        close(pipeDescriptors[1]); //let's start with input
        close(pipeDescriptors[0]);
        return false;
    });

    return Application->run(window);
}
...