Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing GTK and C, how can I start/stop a long calculation (in a seperate thread) using a button?
    primarykey
    data
    text
    <p>Using GTK and C, how can I start/stop a long calculation (in a seperate thread) using a button? I have working code that does just that but I have little confidence that it isa reasonable method (i.e., "right").</p> <p>I have a single button whose label toggles from "start" to "stop". I also have a global pthread_t variable to store a thread. My approach is to either launch or cancel a thread through the button's clicked signal handler depending on the value of a global boolean-like "idle" flag which indicates if the thread is currently running or not.</p> <p>I wanted a working well-designed minimum test case so that I can easily understand the code to adapt for a larger program. This question is very similar to <a href="https://stackoverflow.com/q/13108018/72061">Python&amp;PyGTK: Stop while on button click</a> but that question is in python which I don't know.</p> <p>My code --- posted below --- seems to work but I'm not confident in it because I can easily bring the system to its knees by just clicking the start/stop button a few times in rapid succession. </p> <p>I'd be curious to see how others would (independently) solve this, how their approach compares to mine, and also a code-review for my own approach if it is actually a decent way.</p> <pre><code>#include &lt;gtk/gtk.h&gt; #include &lt;pthread.h&gt; /* suppress unused variable warnings */ #define UNUSED(x) (void)(x) typedef struct _Data { GtkWidget *window1, *button1; gint idle; pthread_t calcthread; } Data; static Data *data; void *calcfunc(void *arg) { int i; UNUSED(arg); data-&gt;idle=FALSE; gtk_button_set_label(GTK_BUTTON(data-&gt;button1),"Stop"); /* This is intended to simulated a long calculation that may finish. Adjust the limit as needed */ for(i=1;i&lt;2e9;++i) { } data-&gt;idle=TRUE; pthread_exit(NULL); } /* this is our click event handler.... it suppose to start or stop the "calcthread" depending on the value of the "idle" flag */ void on_button1_clicked(GtkWidget *widget, Data *ldata) { int ret; UNUSED(widget); UNUSED(ldata); if ( data-&gt;idle==TRUE ) { printf("idle.. starting thread\n"); ret=pthread_create( &amp;data-&gt;calcthread, NULL, calcfunc, NULL); if ( ret !=0 ) { g_error("ERROR: could not create thread\n"); } } else { printf("not idle... canceling thread..."); ret= pthread_cancel( data-&gt;calcthread ); if ( ret != 0 ) { g_error("ERROR: could not cancel thread\n"); } else { printf("canceled\n"); } data-&gt;idle=TRUE; gtk_button_set_label(GTK_BUTTON(data-&gt;button1),"start"); } } /* just defines our setup */ int main (int argc, char *argv[]) { g_thread_init(NULL); gdk_threads_init(); gdk_threads_enter(); gtk_init(&amp;argc, &amp;argv); data=g_slice_new0(Data); data-&gt;idle=TRUE; /* initial state */ printf("idle is %d\n",data-&gt;idle); /* add widgets and objects to our structure */ data-&gt;window1=gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(data-&gt;window1),250,250); data-&gt;button1=gtk_button_new_with_label("Start"); gtk_container_add(GTK_CONTAINER(data-&gt;window1),GTK_WIDGET(data-&gt;button1)); gtk_signal_connect(GTK_OBJECT(data-&gt;window1), "delete-event", gtk_main_quit, NULL); gtk_signal_connect(GTK_OBJECT(data-&gt;button1), "clicked", G_CALLBACK(on_button1_clicked), NULL); gtk_widget_show_all(GTK_WIDGET(data-&gt;window1)); gtk_main(); /* Don't forget to free the memory! */ g_slice_free(Data, data); gdk_threads_leave(); return 0; } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload