How to retrieve data from blocking read in another thread in Gtk3?

情到浓时终转凉″ 提交于 2019-12-23 22:11:34

问题


I have a lib that only expose a blocking theRead function on a streaming data. Now I need to theRead data and show in GTK3 GUI. So I used a transaction channel to pass data from a thread running theRead to GUI thread then read the var via g_idle_add. Apparently this is wrong. The application caused CPU busy. What is the proper way?

Psudo code:

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:


Use IOChannel with pipe:

#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);
}


来源:https://stackoverflow.com/questions/52436541/how-to-retrieve-data-from-blocking-read-in-another-thread-in-gtk3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!