Re: Updating widgets in a thread in a new Gtk::Window
- From: someone_else Safe-mail net
- To: kjell ahlstedt bredband net
- Cc: gtkmm-list gnome org
- Subject: Re: Updating widgets in a thread in a new Gtk::Window
- Date: Tue, 3 Mar 2015 16:13:45 -0500
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_else 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;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]