LINUX.ORG.RU

GTK потоки и вообще

 ,


3

3

У меня 1000 и 1 вопрос по GTK, но самый острый на данный момент это потоки. Читал здесь, здесь, документацию и ещё пару бложиков. Всё равно не осилил. Прошу лоровцев помочь. Вот для примера код:

#include <gtk/gtk.h>

const int BIG_NUM= 9000;

void button1_callback(GtkWidget *button1, gpointer data)
 {
    int i,j,k,l,m;
   
    for(i= 0; i < BIG_NUM; ++i)  
     for(j= 0; j < BIG_NUM; ++j)  
      for(k= 0; k < BIG_NUM; ++k)  
       for(l= 0; l < BIG_NUM; ++l)  
        for(m= 0; m < BIG_NUM; ++m);  
  
 }

void button2_callback(GtkWidget *button2, gpointer data)
 {
     g_printf("Ouch!\n");
 }

int main(int argc, char *argv[])
 {
    GtkWidget *window;
    GtkWidget *button1, *button2;
    GtkWidget *hbox;


    gtk_init(&argc, &argv);

    window= gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_widget_set_size_request(GTK_WIDGET(window), 320, 240);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

    hbox= gtk_hbox_new(FALSE, 0);

    button1= gtk_button_new_with_label("button1");
    button2= gtk_button_new_with_label("button2");

    g_signal_connect(button1, "clicked", G_CALLBACK(button1_callback), NULL);
    g_signal_connect(button2, "clicked", G_CALLBACK(button2_callback), NULL);

    gtk_container_add(GTK_CONTAINER(window), hbox);
    gtk_box_pack_start(GTK_BOX(hbox), button1, TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), button2, TRUE, TRUE, 0);

    gtk_widget_show_all(window);


    gtk_main();

    return 0;
 } 
Как сделать, чтоб первая кнопка не «подвешивала» программу? Апгрейд не предлагать.
На данный момент больше вопросов нет, но они обязательно будут и я их озвучу сюда, чтоб не засорять форум. Заранее спасибо.

★★★★

Я, конечно, не программист, но мне кажется, неправилен сам подход. Интерфейс надо сделать максимально простым и однопоточным. Он должен через неблокирующие механизмы IPC вызывать «бэкенд» в отдельном процессе.

Deleted
()
Ответ на: комментарий от Deleted

Почти так. Вообще не желательно в интерфейсном потоке что-то большое обрабатывать. Иначе интерфейс действительно будет лагать и тормозить.

hibou ★★★★★
()
Ответ на: комментарий от fero

Более подробно:

В void button1_callback(GtkWidget *button1, gpointer data) пишешь pthread_create (...). Эта функция создаст новый поток, который будет выполнятся параллельно гуям. Последняя инструкция в потоке, если нужно что-нить в гуях обносить: gdk_threads_add_idle () с указателями на функцию, которая это сделает.

И помни, ГТК НЕ потокобезопасен.

Rubbiroid
()
Ответ на: комментарий от Rubbiroid

Спасибо. Примеров-то куча, просто они отдельные функции запускают в новый поток, а не функции обрабатывающие события.

fero ★★★★
() автор топика
Ответ на: комментарий от fero

Ну как бы и моем «примере» то же самое. Коллбек (button1_callback) кнопки создает поток (pthread_create), в котором будет выполнятся какая-то функция (параметр к pthread_create). Потом этот поток скажет ГТК «В перерыве выполни эту функцию от своего имени» (gdk_threads_add_idle). И эта последняя функция может нормально обновить гуи.

Не забудь про Race Conditions (хз как по русски) при доступе к данным из разных потоков.

Rubbiroid
()
Ответ на: комментарий от Rubbiroid

Примерно понятно. Попробую. Спасибо ещё раз

fero ★★★★
() автор топика
Ответ на: комментарий от Zhbert

:) ну мне кажется, это мало зависит от инструмента.

Вообще я сам редко пользуюсь дополнительными тредами. Просто мало таких задач. Чаще использую idle-функции. Они исполняются в том же потоке, что и интерфейс, но только когда gtk находится в цикле ожидания и ничего другого не делает. Для повседневных задач этого хватает. Интерфейс не подвешивается и накладных расходов на дополнительный тред нет.

hibou ★★★★★
()
Ответ на: комментарий от hibou

Ваш листинг собрал, посмотрел. Всё замечательно. Благодарю. Теперь вот про idle-функции читаю. Даже не догадывался об их существовании.

fero ★★★★
() автор топика
Ответ на: комментарий от fero

Выбор idle-функция или параллельный тред - зависит от типа задачи. Idle хороши для разных мелких задачек. Или же когда одну большую можно разбить на несколько маленьких периодических. Например, вот как добавление картинок в галерею. Периодически по одной так добавлять в фоне. Если же задача большая, вот как у вас, большой цикл, то наверное лучше дополнительный тред.

Помните, idle исполняются в интерфейсном потоке. Если там считать что-то большое и долгое, интерфейс будет подвисать.

hibou ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.