Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re: how to fork & join in tk?

by marioroy (Curate)
on Apr 23, 2017 at 02:32 UTC ( #1188651=note: print w/replies, xml ) Need Help??


in reply to how to fork & join in tk?

Hello redss,

Forking and joining may cause the app to crash on some platforms. A way around this is to spawn a worker or pool of workers in the background and send messages via a queue. Below please find two demonstrations, one using threads, the other MCE::Hobo. A shared scalar is constructed for updating the message string. A Tk timer is configured to run at 1/10th interval (fraction of a second).

These examples are based on zentura++'s many examples where I've been validating the upcoming MCE 1.828 and MCE::Shared 1.825 releases alongside Tk, Gtk2, Gtk3, Wx, and what not, including Curses::UI.

First, a threads demonstration.

## # see also a demonstration by zentara, particularly -textvariable # http://www.perlmonks.org/?node_id=1087787 # # my $msg : shared = "Start"; # $btn1 = $mw->Button(-textvariable => \$msg, ...); # later : $msg = "Step Two"; $btn1->update; # # thank you, zentara++ ## use strict; use warnings; use threads; use threads::shared; use Thread::Queue; use Tk; my $que = Thread::Queue->new(); my $msg : shared = "Start"; # detach the thread so not to get thread warnings # about running threads when exiting the app (my $thr = threads->create('bg_task'))->detach(); my $mw = MainWindow->new(); $mw->protocol( WM_DELETE_WINDOW => \&quit ); $mw->geometry("+150+100"); $mw->Label( -text => "Tk + threads Demo", -height => 2, -width => 22 ) +->pack; my $btn1 = $mw->Button( -text => $msg, -command => \&fun, -width => 10 + ); $btn1->pack(); my $btn2 = $mw->Button( -text => "Quit", -command => \&quit, -width => + 10 ); $btn2->pack(); my $timer = $mw->repeat( 100, sub { $btn1->configure( -text => $msg ); }); MainLoop(); sub fun { $que->enqueue("some event"); return; } sub quit { $timer->cancel; # for threads, is helpful to signal the app to # terminate so not to segfault on some platforms kill('TERM', -$$); exit; } sub bg_task { while ( my $event = $que->dequeue ) { $msg = "Step One"; sleep 1; $msg = "Step Two"; sleep 1; $msg = "Step Three"; } }

Likewise, a MCE::Hobo demonstration. This does a fork.

## # see also a demonstration by zentara, particularly -textvariable # http://www.perlmonks.org/?node_id=1087787 # # tie my $msg, 'MCE::Shared', "Start" # $btn1 = $mw->Button(-textvariable => \$msg, ...); # later : $msg = "Step Two"; $btn1->update; # # thank you, zentara++ ## use strict; use warnings; use Tk; use MCE::Hobo; use MCE::Shared; my $que = MCE::Shared->queue(); my $msg = MCE::Shared->scalar("Start"); my $hobo = MCE::Hobo->create('bg_task'); my $mw = MainWindow->new(); $mw->protocol( WM_DELETE_WINDOW => \&quit ); $mw->geometry("+150+100"); $mw->Label( -text => "Tk + MCE::Hobo Demo", -height => 2, -width => 22 + )->pack; my $btn1 = $mw->Button( -text => $msg->get, -command => \&fun, -width +=> 10 ); $btn1->pack(); my $btn2 = $mw->Button( -text => "Quit", -command => \&quit, -width => + 10 ); $btn2->pack(); my $timer = $mw->repeat( 100, sub { $btn1->configure( -text => $msg->get ); }); MainLoop(); sub fun { $que->enqueue("some event"); return; } sub quit { $timer->cancel; $hobo->exit->join; exit; } sub bg_task { while ( my $event = $que->dequeue ) { $msg->set("Step One"); sleep 1; $msg->set("Step Two"); sleep 1; $msg->set("Step Three"); } }

Thank you Discipulus for introducing zentara recently. Zentara, am pleased to meet you. I've used a couple examples of yours for validating signal handling improvements in MCE 1.828 and MCE::Shared 1.825. I will post what and how after release day, possibly here. But that thread frightens me for some reason. Imho, folks may use any parallel module of their liking or do things by hand if that feels more natural.

Well redss, am not sure if this will work for you. It may be helpful to do a search at the monastery for more Tk demonstrations. I wonder what other folks do myself. For more MCE::Hobo demonstrations, see also this thread by karlgoethebier.

Regards, Mario

This thread is helpful for updating a Tk label. This is where I've learn to update a Tk widget with ->configure.

Found an old post by zentara: Re: Perl Tk and Threads.

Replies are listed 'Best First'.
Re^2: how to fork & join in tk?
by marioroy (Curate) on Apr 23, 2017 at 07:51 UTC

    If running on a Unix platform, you're in luck. One can spawn a Hobo process while Tk is running.

    For this demonstration, it's best to disable the button prior to spawning to prevent running two or more Hobos. The text is updated just like before with "Step One", "Step Two", etc. Finally, the button state is set back to normal after the Hobo completes processing.

    The hobo variable is either defined or not defined. Thus, state-like in itself.

    use strict; use warnings; use Tk; use MCE::Hobo; use MCE::Shared; my $msg = MCE::Shared->scalar("Step One"); my $hobo; my $mw = MainWindow->new(); $mw->protocol( WM_DELETE_WINDOW => \&quit ); $mw->geometry("+150+100"); $mw->Label( -text => "Tk + MCE::Hobo Demo", -height => 2, -width => 22 + )->pack; my $btn1 = $mw->Button( -text => "Start", -command => \&fun, -width => + 10 ); $btn1->pack; my $btn2 = $mw->Button( -text => "Quit", -command => \&quit, -width => + 10 ); $btn2->pack; my $timer = $mw->repeat( 100, sub { return unless $hobo; my $text = $msg->get; $btn1->configure( -text => $text ); if ( $hobo->is_joinable ) { $hobo->join; if ( my $err = $hobo->error ) { print {*STDERR} "something went wrong: $err\n"; } $btn1->configure( -state => "normal" ); $hobo = undef; } }); MainLoop(); sub fun { # important, disable button and reset the shared variable $btn1->configure( -state => "disabled" ); $msg->set("Step One"); $hobo = MCE::Hobo->create( sub { sleep 1; $msg->set("Step Two"); sleep 1; $msg->set("Step Three"); }); return; } sub quit { $timer->cancel; $hobo->exit->join if $hobo; exit; }

    Q. Why does this work using MCE::Hobo?

    A. Hobos exit by calling CORE::kill("KILL", $$) when Tk is present to bypass any destructors during exiting.

    Regards, Mario

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1188651]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (2)
As of 2017-08-19 12:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Who is your favorite scientist and why?



























    Results (310 votes). Check out past polls.

    Notices?