LINUX.ORG.RU

вопрос по gtk


0

0

Есть прога написанная на gtk которая раз в секунду обновляет свой екран так вот между обновлениями екрана main loop является застопорённым а он должен решать некоторые задачи например сортировать отображаемые на екране данные

Посоветуйте как разблокировать main loop

anonymous

Все действия, которые занимают большое время (>1 секунды) имеет смысл реализовывать в отдельном потоке, испольняющемся параллельно.

anonymous
()

>Есть прога написанная на gtk которая раз в секунду обновляет свой >екран так вот между обновлениями екрана main loop является >застопорённым а он должен решать некоторые задачи например >сортировать отображаемые на екране данные 

>Посоветуйте как разблокировать main loop.

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

Цикл, который работает долго:

for (i=0; i<10000; i++)
{
  do_calculation (data);
}

Заменяется на:

struct iterator {
 int i;
 gpointer data;
};

gboolean idle_callback (gpointer data)
{
 struct iterator *iter = (struct iterator *data);

 iter->i++;
 if (i == 10000) return TRUE;

 do_calculation (iter->data);
 return FALSE;
}

main
{
  struct iterator iter;
  gtk_init();

  iter.i = 0;
  iter.data = data;
  g_idle_add (idle_callback, (gpointer)&iter);
  gtk_main();
}

Хотя по описанному схема работы программы немного непонятна. Во-первых, main_loop должен решать задачи отображения и сбора событый, а не сортировать данные. Данные должны сортироваться в обработчиках событий или во время простоя (idle). При этом main_loop должен работать постоянно, а данные обрабатываться или в других нитях, или по той схеме, которая описана выше. 

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

А как засинхронизировать между собой родительский и дочерний поток???

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

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

gtk_timeout_add(REFRESH_TIMEOUT, get_data_callback, main_treeview);

а ф-ю сортировки установил следующим образом

gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE(treemodel), sort_callback, NULL, NULL);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(treemodel),
GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
GTK_SORT_ASCENDING);

так вот получается что данные на екране обновляются не одновременно а случайными партиями с задержкой между обновлениями n*REFRESH_TIMEOUT, где n - целое число. а коль REFRESH_TIMEOUT достаточно большой(~10c) то создаётся достаточно неприятное ощущение кроме того данные должны отображатся на екране сразу а не через пол-минуты когда они могут быть уже ненужными.

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

тоесть насколько я понял проблема заключается в том что gtk_timeout_add() стопорит майн луп на каждом цикле на REFRESH_TIMEOUT сек

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

1. Не понял утверждения. Если данные поступают через промежуток времени REFRESH_TIMEOUT, то они и на экране должны появляться через REFRESH_TIMEOUT. При чем здесь n*REFRESH_TIMEOUT? Или данных много? Сколько в среднем данных добавляется за 10c? Может, процесс сортировки занимает большое время. Если поток данных велик, то, возможно, выбранное отображение с помощью TreeModelSort некорректно.

2. Есть предложение собирать данные не по timeout'у, а по мере поступления. Для этого можно организовать GSource (источник событий) и добавить его в main_loop. Тогда по мере поступления данных их можно читать и добавлять в TreeModel для отображения. Процесс будет происходить гладко. Для примера можно посмотреть функцию g_io_watch_add, хотя можно использовать и более усложненую конструкцию.

3. потоки синхронизируются при помощи стандартных средств синхронизации - mutex'ов, сообщений.

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

1)данных очень немного около 16 значений типа double 2)данные на екране не добавляются а обновляются всё теже 16 записей 3)данные ДОЛЖНЫ появлятся сразу после прихода но почему-то после записи в TreeModel на екране они отображаются спустя n*REFRESH_TIMEOUT почему - не знаю, это собственно и есть то с чем я борюсь. Предполагаю что проблема в реализации толи сортировки толи gtk_timeout_add()

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

Видимо есть проблемы в реализации все-таки есть проблемы в
реализации. Вот небольшой пример. 

#include <gtk/gtk.h>
double iterator = 0;

enum {
COLUMN_1,
COLUMN_2
};

void init_model (GtkListStore *store)
{
  GtkTreeIter iter;
  
  gtk_list_store_append (store, &iter);
  gtk_list_store_set (store, &iter, COLUMN_1, "First", -1);
  gtk_list_store_append (store, &iter);
  gtk_list_store_set (store, &iter, COLUMN_1, "Second", -1);
  gtk_list_store_append (store, &iter);
  gtk_list_store_set (store, &iter, COLUMN_1, "Third", -1);
  gtk_list_store_append (store, &iter);
  gtk_list_store_set (store, &iter, COLUMN_1, "Fourth", -1);
}

gboolean timeout_fn (gpointer data)
{
 int j;
 GtkListStore *store = GTK_LIST_STORE(data);
 gboolean valid;
 GtkTreeIter iter;
  
 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter);
 for (j=0; j<4; j++)
 { 
   gtk_list_store_set (store, &iter, COLUMN_2, iterator, -1 );
   valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
   iterator+=1.0;
 }
}


int main (int argc, char *argv[])
{
  GtkWidget *window;
  GtkListStore* store;
  GtkTreeModel* sort_model;
  GtkWidget *view;
  
  GtkTreeViewColumn *column;
  GtkCellRenderer *renderer;
  
  gtk_init (&argc, &argv);
  store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_DOUBLE);
  sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(store));
  view = gtk_tree_view_new_with_model (sort_model);
  gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(view), TRUE);

  g_object_unref (store);
  g_object_unref (sort_model);

  renderer = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes ("First column",
                                                     renderer,
						     "text",
                                                     COLUMN_1, NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
  gtk_tree_view_column_set_sort_column_id (column, COLUMN_1);

  renderer = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes ("Second column",
                                                     renderer,
                                                     "text",
                                                     COLUMN_2, NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
  gtk_tree_view_column_set_sort_column_id (column, COLUMN_2);

  init_model (store);
  g_timeout_add (1000, timeout_fn, store);
 
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  g_signal_connect (G_OBJECT(window),"destroy", G_CALLBACK(gtk_main_quit), NULL);
  gtk_container_add (GTK_CONTAINER (window), view);
  gtk_widget_show_all (window);
  
  
  gtk_main();
}

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

Пока большое спасибо. Буду вникать поглубже. в gtk я пока-что только начинающий. если будут ещё вопросы было бы неплохо обратится лично.

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