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

Re: forked process exiting before output read



On Fri, 27 Jul 2007 16:01:16 +0200
"Jeffrey Ratcliffe" <jeffrey ratcliffe gmail com> wrote:

>
>Sometimes, updating the GUI takes longer than the child process, and
>so the child process exits before the GUI has read all the data,
>meaning that the last few images are missing. The following code
>illustrates the point - the ProgressBar never reaches 100%.
>
>Whilst I realise that I can write the info to a file, rather than the
>socket (or pipe), or I could maintain a buffer, rather than reading
>from the pipe a line at a time. Is there a Right Way to do this? Maybe
>some way of signalling to the child process when the parent has
>finished?
>Regards
>Jeff

If you use a thread, you can avoid this by placing the results in a shared variable.

Here is a simple threads example to give you the idea, it uses a reusable thread.
All you need to do, is store your thread's results in a shared var, and read it.

#!/usr/bin/perl
use warnings;
use strict;
use threads;
use threads::shared;
use Glib qw/TRUE FALSE/;
use Gtk2 qw/-init -threads-init/;

Glib::Object->set_threadsafe (TRUE);

#setup shared hash
my %shash;
share(%shash); #will work for first level keys

$shash{'go'} = 0;
$shash{'work'} = '';
$shash{'die'} = 0;

my $num:shared = 0;


my $window = Gtk2::Window->new('toplevel');
$window ->signal_connect( 'destroy' => \&delete_event );
$window->set_border_width(10);
$window->set_size_request(300,300);

my $vbox = Gtk2::VBox->new( FALSE, 6 );
$window->add($vbox);
$vbox->set_border_width(2);

my $hbox= Gtk2::HBox->new( FALSE, 6 );
my $hbox1 = Gtk2::HBox->new( FALSE, 6 );
$vbox->pack_end($hbox,FALSE,FALSE,0);
$vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0);
$vbox->pack_end($hbox1,FALSE,FALSE,0);
$hbox->set_border_width(2);
$vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0);

my $ebutton = Gtk2::Button->new_from_stock('gtk-quit');
$hbox->pack_end( $ebutton, FALSE, FALSE, 0 );
$ebutton->signal_connect( clicked => \&delete_event );

my $pbar = Gtk2::ProgressBar->new();
$pbar->set_pulse_step(.1);
$hbox->pack_start($pbar,1,1,0);


my $label_w_markup = Gtk2::Label->new();
$label_w_markup->set_markup("<span foreground=\"yellow1\" 
  size=\"40000\">$num</span>");

$vbox->pack_end($label_w_markup,FALSE,FALSE,4);	

######################################################

my $tbutton = Gtk2::Button->new_with_label('Run Thread');
 $hbox1->pack_start($tbutton , 1, 1, 0 );
my $lconnect = $tbutton->signal_connect( clicked => sub{ launch() });
my $sconnect;

$window->show_all();
$pbar->hide;   #needs to be called after show_all

#create 1 sleeping thread passing it the label and pbar to control
my $thread = threads->new(\&work, $label_w_markup, $pbar);

Gtk2->main;
######################################
sub delete_event {
  $shash{'go'} = 0;
  $shash{'die'} = 1;
  $thread->join;
  Gtk2->main_quit;
  return FALSE;
}
#######################################
sub launch{
   $pbar->show;
   $tbutton->set_label('Stop Thread');
   $tbutton->signal_handler_block($lconnect);
   $sconnect = $tbutton->signal_connect( clicked => sub{ stop() });
   $shash{'go'} = 1;
}
##################################################
sub stop{
   print "stopped\n";
   $shash{'go'} = 0;
   $pbar->hide;
   $tbutton->set_label('Run Thread');
   $tbutton->signal_handler_block ($sconnect);
   $tbutton->signal_handler_unblock ($lconnect);
}
#########################################################
sub work{
    
    my ($label,$pbar) = @_;
    $|++; 
    while(1){
       if($shash{'die'} == 1){ return }; 
      
       if ( $shash{'go'} == 1 ){
        
         $num = 0;
         while(1){
            	$num++;
            	
            	if($num > 30){last}
            	     
                 Glib::Idle->add(
	           sub{
	            if($shash{'die'} == 1){ return };
	            $label->set_markup("<span foreground=\"yellow1\" 
                    size=\"40000\">$num</span>");
                    $pbar->pulse;
		    return FALSE;
		   });
                
	        select(undef,undef,undef, .1);

            if($shash{'go'} == 0){last}
            if($shash{'die'} == 1){ return }; 
           }
       
       #if reach this point, the thread has finished
          print "my results = $num\n";   

         Glib::Idle->add(
	           sub{
	            if($shash{'die'} == 1){ return };
	            $label->set_markup("<span foreground=\"green\" 
                    size=\"60000\">$num</span>");
                    $pbar->hide;
                    return FALSE;
		   });
       
           $shash{'go'} = 0; #turn off self before returning      
       }else
         { select(undef,undef,undef,.1) } #sleep time
    }
}
##############################################



__END__

-- 
I'm not really a human, but I play one on earth.
http://zentara.net/japh.html



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