> When I read your post, I get the impression that you already know what's 
> wrong with your program. Or at least have a strong suspicion.
> 
> You update TestWindow::m_entry in the worker thread. That's not safe. Most of 
> gtk+ and gtkmm are not thread-safe. You shall call widget functions only in 
> the main thread.
> 
> Have you seen the example program in the gtkmm tutorial?
> https://developer.gnome.org/gtkmm-tutorial/stable/sec-multithread-example.html.en
> 
> Kjell
> 
> Den 2015-03-03 07:12, someone_e...@safe-mail.net skrev:
> 
> > 
> > Hello, I was reading the gtkmm tutorial and it says "Use Glib::Dispatcher 
> > to invoke gtkmm functions from worker threads." I have two Gtk::Windows, 
> > main window and a view window. What I would like to do is have a thread 
> > that will update some widgets (Entrys, lables, and a 
> > Glib::RefPtr<Gdk::Pixbuf>) in the second window, because after the work is 
> > done the results will be displayed in that new window. So what I did was I 
> > show the new window and then thread the worker function in the new window. 
> > The worker function updates the widgets, 
> 
> Don't do that.
> > 
> >  which I think is not thread safe 
> 
> Correct
> > 
> >  because after calling the thread x amount of times, the program will 
> > crash. //Is this OK to do in a thread? Even for a 
> > Glib::RefPtr<Gdk::Pixbuf>? m_entry.set_text("blah"); 
> 
> No, do it in the main thread (the GUI thread).
> 

Thank you everybody for the help. Here is how I coded it: (example)

//test.h
#ifndef TEST_H_
#define TEST_H_

#include "worker.h"

class MainWindow : public Gtk::Window
{
public:
        MainWindow();
        virtual ~MainWindow(); 
        
protected:
        void Button();
        
protected:
        Gtk::Button m_btn;
        
private:
        TestWindow m_test_win;
};
#endif /* TEST_H_ */

//worker.h
#ifndef WORKER_H_
#define WORKER_H_

#include <gtkmm.h>

class MainWindow;

class TestWindow : public Gtk::Window
{
public:
        TestWindow();
        virtual ~TestWindow();
        void DoWork();
        
protected:
        Gtk::HBox m_box_main;
        Gtk::Entry m_entry;
        
private:
        void DispatcherUpdateEntry(bool done);
        void ThreadUpdateEntry();
        void GetDone(bool* done);
        
private:
        bool m_work_done;
        Glib::Threads::Thread* m_thread;
        Glib::Dispatcher m_dispatcher;
        mutable Glib::Threads::Mutex m_mutex;
};

#endif /* WORKER_H_ */

//test.cpp
#include <gtkmm.h>

#include "test.h"

using namespace std;

MainWindow::MainWindow()
{
        this->set_size_request(300, 300);
        
        this->add(m_btn);
        m_btn.set_label("Call Thread");
        m_btn.signal_clicked().connect(sigc::mem_fun(*this, 
&MainWindow::Button));
                
        this->show_all_children();
}

MainWindow::~MainWindow()
{
        
}

void MainWindow::Button()
{
        m_test_win.show();
        m_test_win.DoWork();
}

int main(int argc, char** argv)
{       
        Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, 
argv, "app.test");
        
        MainWindow main_window;
        
        return app->run(main_window);
}

//worker.cpp
#include "worker.h"

TestWindow::TestWindow()
{
        m_work_done = false;
        
        this->add(m_box_main);
        m_box_main.pack_start(m_entry);
        m_dispatcher.connect(sigc::mem_fun(*this, 
&TestWindow::ThreadUpdateEntry));
        
        m_thread = Glib::Threads::Thread::create(sigc::mem_fun(*this, 
&TestWindow::DoWork));
        
        this->show_all_children();
}

TestWindow::~TestWindow()
{
        
}

void TestWindow::DoWork()
{
        DispatcherUpdateEntry(false);
        //work
        
        DispatcherUpdateEntry(true);
}

void TestWindow::GetDone(bool* done)
{
        Glib::Threads::Mutex::Lock lock(m_mutex);
        *done = m_work_done;
}

void TestWindow::DispatcherUpdateEntry(bool done)
{
        {
                Glib::Threads::Mutex::Lock lock(m_mutex);
                m_work_done = done;
        }
        
        m_dispatcher.emit();
}

void TestWindow::ThreadUpdateEntry()
{
        m_entry.set_text("Hello");
        
        bool done = false;
        GetDone(&done);
        
        if(done == true)
        {
                m_thread->join();
                m_thread = 0;
        }
}
_______________________________________________
gtkmm-list mailing list
gtkmm-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtkmm-list

Reply via email to