errol wrote:
The fact that you are getting it to partially work is only due to luck.
You will need to re-write you code so that ALL GTK/GDK calls are made in the main thread, as under MS Windows GTK is not thread safe. You should not use gdk_threads_enter()/gdk_threads_leave() under MS Windows as calls to GTK/GDK MUST NOT be called from multiple threads.
You can use GLib from multiple threads as that is thread safe, so you can use it for message passing between multiple threads.
Here is the new code, working 100% on linux, virtualbox xp, windows xp.
inserted code:
"static gboolean time_handler_catch_final( gpointer data )" catch bWorking == FALSE and destroy dialog.
"g_thread_create( &thread, ( void * )pcClass, TRUE, NULL );" joinable
"g_thread_join( Thread );" wait thread finish.
gdk_threads_enter()/gdk_threads_leave() is working 100% on xp
Code:
typedef class cList cLIST, *pcLIST;
class cList {
protected:
public:
gboolean bStop;
gboolean bWorking;
GtkWidget *dialog;
GtkWidget *cancel;
GtkWidget *pbar;
cList( pBOOL pbInitStatus );
~cList( void );
};
cLIST::cList( pBOOL pbInitStatus ) {
bStop = FALSE;
bWorking = TRUE;
}
cLIST::~cList( void ) {
}
static void *thread( gpointer ptr ) {
pcLIST pcClass = ( pcLIST )ptr;
CHAR szPercent[ 30 ] = "";
ULONG ulRows;
CHAR szBuffer[ __BUFSIZ + 1 ];
DOUBLE dbPercent;
int i = 0;
int k = 200;
do {
dbPercent = (( DOUBLE )( i + 1 ) * 100.0 ) / ( DOUBLE )k;
sprintf( szPercent, "%.2lf%%", dbPercent );
gdk_threads_enter();
gtk_progress_bar_set_text( GTK_PROGRESS_BAR( pcClass->pbar ), szPercent );
gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR( pcClass->pbar ), ( dbPercent / 100.0 ) );
gdk_flush();
gdk_threads_leave();
g_usleep( 1000 );
} while (( !pcClass->bStop ) && ( ++i < k ));
pcClass->bWorking = FALSE;
g_thread_exit( NULL );
return( NULL );
}
static void cancel( GtkWidget *widget,
gpointer data ) {
pcLIST pcClass = ( pcLIST )data;
pcClass->bStop = TRUE;
//gtk_widget_destroy( pcClass->dialog );
}
static gboolean time_handler_catch_final( gpointer data ) {
pcLIST pcClass = ( pcLIST )data;
if ( pcClass->bWorking == FALSE ) {
gtk_widget_destroy( pcClass->dialog );
return( FALSE );
}
return TRUE;
}
void gtkList( GtkWidget *widget,
gpointer data ) {
BOOL bInitStatus = TRUE;
pcLIST pcClass = new cLIST( &bInitStatus );
GThread *Thread;
if ( pcClass != NULL ) {
GtkWidget *main_vbox;
GtkWidget *main_hbox;
GtkWidget *hbox;
GtkWidget *hseparator;
pcClass->dialog = gtk_dialog_new();
gtk_window_set_modal( GTK_WINDOW( pcClass->dialog ), GTK_DIALOG_MODAL );
gtk_container_set_border_width( GTK_CONTAINER( pcClass->dialog ), 0 );
gtk_window_set_resizable( GTK_WINDOW( pcClass->dialog ), FALSE );
gtk_window_set_position( GTK_WINDOW( pcClass->dialog ), GTK_WIN_POS_CENTER );
gtk_widget_set_size_request( GTK_WIDGET( pcClass->dialog ), 300, 80 );
main_vbox = gtk_vbox_new( FALSE, 0 );
gtk_container_set_border_width( GTK_CONTAINER( main_vbox ), 0 );
gtk_container_add( GTK_CONTAINER( GTK_DIALOG( pcClass->dialog )->vbox ), main_vbox );
hseparator = gtk_hseparator_new();
gtk_box_pack_start( GTK_BOX( main_vbox ), hseparator, TRUE, TRUE, 0 );
pcClass->pbar = gtk_progress_bar_new();
gtk_box_pack_start( GTK_BOX( main_vbox ), pcClass->pbar, FALSE, FALSE, 0 );
gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR( pcClass->pbar ), 0.0 );
gtk_progress_bar_set_orientation( GTK_PROGRESS_BAR( pcClass->pbar ), GTK_PROGRESS_LEFT_TO_RIGHT );
hseparator = gtk_hseparator_new();
gtk_box_pack_start( GTK_BOX( main_vbox ), hseparator, TRUE, TRUE, 0 );
hbox = gtk_hbox_new( FALSE, 0 );
gtk_box_pack_start( GTK_BOX( main_vbox ), hbox, TRUE, TRUE, 0 );
pcClass->cancel = gtk_button_new_with_label( "Cancel" );
gtk_box_pack_start( GTK_BOX( hbox ), pcClass->cancel, TRUE, TRUE, 0 );
g_signal_connect( G_OBJECT( pcClass->cancel ), "clicked", ( GCallback )cancel, pcClass );
gtk_widget_show_all( pcClass->dialog );
Thread = g_thread_create( &thread, ( void * )pcClass, TRUE, NULL );
g_timeout_add( 100, ( GSourceFunc )time_handler_catch_final, ( gpointer )pcClass );
gtk_dialog_run( GTK_DIALOG( pcClass->dialog ));
g_thread_join( Thread );
}
if ( pcClass != NULL ) delete pcClass;
} // ***** Function gtkList ***** //