Hello. I created a simple function cb that runs infinitely in a thread. It increments and integer value and shows it in a GtkTextView widget. I want to stop the task with a button.
The code I have right now freezes the whole app when the button is pressed and the program becomes unresponsive. What should I change to make the button stop the cb function and the thread it runs in without freezing the whole app?
GtkWidget *dataView;
GTask *task;
GCancellable *cancellable;
GObject *object;
int main (int argc, char *argv[]) {
//starting application
return startApp("exe.taskTest", G_APPLICATION_DEFAULT_FLAGS, activateApp, argc, argv);
}
int startApp(char *id, GApplicationFlags flags, void (*activateFunc), int argc, char *argv[]) {
GtkApplication *app;
int stat;
app=gtk_application_new(id, flags);
g_signal_connect(app, "activate", G_CALLBACK(activateFunc), NULL);
stat=g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return stat;
}
tatic void activateApp (GApplication *app) {
//let's imagine that we created gtkApplicationWindow here
//and GtkGrid to store widgets below inside of it
...
//just a part of GtkTextView initialisation
dataView=gtk_text_view_new();
GtkTextBuffer *dataViewBuffer;
dataViewBuffer=gtk_text_buffer_new(NULL);
gtk_text_view_set_buffer(GTK_TEXT_VIEW(dataView), dataViewBuffer);
...
//just a button initialisation
GtkWidget *cancelTaskButton;
cancelTaskButton=initButton("Cancel", cancelTaskCallback, portValues);
//I skipped over adding those elements to the grid
...
//TASK CODE
object=g_object_new(G_TYPE_OBJECT, NULL);
cancellable=g_cancellable_new();
task=g_task_new(object, cancellable, cb, NULL);
g_task_set_task_data(task, NULL, cbDestroy);
g_task_run_in_thread(task, (void *)cb);
g_object_unref(cancellable);
g_object_unref(object);
g_object_unref(task);
//TASK CODE END
gtk_window_present(GTK_WINDOW(win));
}
void cb() {
char infoString[50];
static int x=0;
do {
sprintf(infoString, "%d", x);
static void *data[2];
data[0]=dataView;
data[1]=infoString;
g_idle_add_once((void *)setText, data);
g_usleep(1); //needed, otherwise the program crashes
x++;
}
while (1);
}
void cbDestroy() {
//nothing to free(?)
}
void setText(void* data[]) {
setTextInTextView(data[0], data[1]);
}
void setTextInTextView(GtkWidget *textView, char *text) {
GtkTextBuffer *infoBuffer=gtk_text_buffer_new(NULL);
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(infoBuffer), text, strlen(text));
gtk_text_view_set_buffer(GTK_TEXT_VIEW(textView), infoBuffer);
}
static void cancelTaskCallback(GtkButton *button, void *data[]) {
g_task_set_return_on_cancel(task, TRUE);
g_cancellable_cancel(cancellable);
}