Threads...



Hello!

I have kind of a conceptual problem concerning a multithreaded app.
Let me describe the following small scenario:

Below you can see a very simple gtk+ program (or at least the important
parts of it). In the main function the threads environment is initialized,
then a "dialog_init" is created and shown:

int main(int argc, char **argv)
{
	if (!g_thread_supported ())
	{
		g_thread_init (NULL);
		gdk_threads_init();
		printf("Threads initialized\n");
	}
	else
	{
		printf("Threads not supported!\n");
		exit(1);
	}
	gtk_init(&argc, &argv);

	dialog_init = create_dialog_init();
	gtk_widget_show(dialog_init);

	gdk_threads_enter();
	gtk_main();
	gdk_threads_leave();
}

The purpose of this "dialog_init" is to

	1) call the function "init_app()", which does the actual initialization stuff
	   (which takes a long time), and

	2) display and update a progress bar until init_app() is finished.

I have implemented this in the following way, which actually works fine:

void on_dialog_init_show()
{
	...
	g_timeout_add(10,on_dialog_init_login_update_pb,NULL);
	g_init = g_thread_create(t_init,NULL,FALSE,&error);
}

gboolean on_dialog_init_login_update_pb(gpointer data)
{
	... update the progress bar...
	if (init_finished) return FALSE;
	else return TRUE;
}

void *t_init(void *p)
{
	init_app();
	init_finished = 1;  // global var, indicates that init_app() has finished
	return NULL;
}

on_dialog_init_login_update_pb is called periodically and updates the pb,
until init_app is finished.

Now during initialization it is necessary to occasionally popup messageboxes,
ie. it might be the case, that from somewhere within init_app() a messagebox
is shown.

init_app() is a function which doesn't know anything about gtk+ (since I want
it to be independent from a GUI), therefore I provide a callback function
(cb_messagebox) to init_app, which - when called - shows a messagebox.

Since init_app() runs in a separate thread, it is necessary to use
gdk_threads_enter and gdk_threads_leave, therefore I have changed the
thread function to:

void *t_init(void *p)
{
	gdk_threads_enter();
	init_app(cb_messagebox);
	gdk_threads_leave();

	init_finished = 1;  // global var, indicates that init_app() has finished
	return NULL;
}

void cb_messagebox(char *msg_text)
{
	// popup a gtk+ messagebox displaying
	// msg_text
	...
	gtk_dialog_run(...);
	...
}

Unfortunately now the progress bar is no longer updated, which is quite clear,
since the call to gdk_threads_enter in t_init blocks all 'drawing requests' 
from outside this thread, especially those from the progress bar, until
gdk_threads_leave is called.

My question now is: how can I solve or avoid this problem?
I _need_ to popup messageboxes from within init_app (which forces me to use
gdk_threads_enter), but I still want the progress bar to be updated.

What I could do is not to use gdk_threads_enter in t_init, but in
cb_messagebox (before the call to gtk_dialog_run), but this is not a good 
soluion, since cb_messagebox is sometimes called from within a separate
thread, and sometimes from within the main process (which inhibits the use of
gdk_threads_enter).

Tricky...

Looking forward for suggestions!
Thanks!
Christian




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]