http://www.perlmonks.org?node_id=858601

Smile-n-Nod has asked for the wisdom of the Perl Monks concerning the following question:

use threads; use threads::shared; use Tk; # If these two hashes are shared (as below), the Entry widget displays # "Original"; if they are not shared, the widget displays "Changed". # %top_hash; # %hash; share(%top_hash); share(%hash); $top_hash{A} = \%hash; $top_hash{A}{B} = 'Original'; $t = MainWindow->new()->Scrolled('Text')->pack(); $e = $t->Entry(-textvariable => \$top_hash{A}{B}); $t->windowCreate('end', -window => $e); $t->insert('end', "\n"); $top_hash{A}{B} = 'Changed'; MainLoop;
If %top_hash and %hash are shared (as above), this script displays an Entry widget which contains "Original". If those hashes are not shared, the Entry widget display "Changed." Why doesn't the Entry widget update its display when I set -textvariable to a reference to a shared hash?
  • Comment on perl/Tk Entry widget displays wrong value when -textvariable is shared
  • Download Code

Replies are listed 'Best First'.
Re: perl/Tk Entry widget displays wrong value when -textvariable is shared
by zentara (Archbishop) on Sep 02, 2010 at 17:30 UTC
    You are ecncountering a problem with threads:shared hashes where only the first level keys get shared by default. When you run as shared, the $top_hash{A}{B} gets ignored as being shared, while it runs fine in normal perl.

    To amplify a bit, the Tk eventloop will never respond to a change in threads shared variables, when they are across thread boundaries. You don't have actual threads here, but you need to setup a timer, to read for any changes in the shared variable. So you can't use tied variables effectively across threads without timers. Try this:

    #!/usr/bin/perl use warnings; use strict; use threads; use threads::shared; use Tk; my %top_hash; share $top_hash{'A'}{'B'}; $top_hash{'A'}{'B'} = 'Original'; my $t = MainWindow->new()->Scrolled('Text')->pack(); my $e = $t->Entry(-textvariable => \$top_hash{'A'}{'B'}); $t->windowCreate('end', -window => $e); $t->insert('end', "\n"); my $timer = $t->after(3000,sub{$top_hash{'A'}{'B'} = 'Changed'}); MainLoop;

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh