Updating widgets in a thread in a new Gtk::Window



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, which I think is not thread safe because after calling the 
thread x amount of times, the program will crash.

The following example works but sometimes my program will crash.
 Example:

//worker.h
#ifndef WORKER_H_
#define WORKER_H_

#include <gtkmm.h>

class MainWindow;

class TestWindow : public Gtk::Window
{
public:
 TestWindow();
 virtual ~TestWindow();
 bool WorkDone();
 void DoWork(MainWindow* main_window);
 
protected:
 Gtk::HBox m_box_main;
 Gtk::Entry m_entry;
 
private:
 bool m_work_done;
};

#endif /* WORKER_H_ */

//test.h

#ifndef TEST_H_
#define TEST_H_

#include "worker.h"

class MainWindow : public Gtk::Window
{
public:
 MainWindow();
 virtual ~MainWindow();
 void ThreadDone();
 void Notify();
 
protected:
        void Button();
 
protected:
 Gtk::Button m_btn;
 
private:
 Glib::Threads::Thread* m_thread;
 TestWindow m_test_win;
 Glib::Dispatcher m_dispatcher;
};

#endif /* TEST_H_ */

//test.cpp

#include <gtkmm.h>

#include "test.h"

using namespace std;

MainWindow::MainWindow()
{
 m_thread = 0;
 
 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));
 
 m_dispatcher.connect(sigc::mem_fun(*this, &MainWindow::ThreadDone));
 
 this->show_all_children();
}

MainWindow::~MainWindow()
{
 
}

void MainWindow::Button()
{
 m_test_win.show();
 
 if(!m_thread)
 {
    m_thread = Glib::Threads::Thread::create(sigc::bind(sigc::mem_fun(m_test_win, &TestWindow::DoWork), 
this));
  m_btn.set_sensitive(false);
 }
}

void MainWindow::ThreadDone()
{
 if(m_thread && m_test_win.WorkDone())
 {
  m_thread->join();
  m_thread = 0;
  m_btn.set_sensitive(true);
 }
}

void MainWindow::Notify()
{
      m_dispatcher.emit();
}

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"
#include "test.h"

TestWindow::TestWindow()
{
 m_work_done = false;
 
 this->add(m_box_main);
 m_box_main.pack_start(m_entry);
 
 this->show_all_children();
}

TestWindow::~TestWindow()
{
 
}

void TestWindow::DoWork(MainWindow* main_window)
{
 m_work_done = false;
 m_entry.set_text("");
 
 //Is this OK to do in a thread? Even for a Glib::RefPtr<Gdk::Pixbuf>?
 m_entry.set_text("blah");
 
 m_work_done = true;
 main_window->Notify();
}

bool TestWindow::WorkDone()
{
 return m_work_done;
}

Thank you so much!


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]