Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Tk::ProgressBar + LWP

by Anonymous Monk
on Jul 03, 2013 at 20:26 UTC ( [id://1042275]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hey guys, I am currently trying to write an application that downloads a file and dynamically displays the progress in a Tk Widget. The program should be capable of downloading multiple files simultaneously. I considered a separate thread for each progress bar and sharing the progress bar's variable with the thread which updates the variable. Unfortunately I have discovered that Tk is not thread safe and that this approach causes issues. How can I accomplish this without using threads? For the record I am using the "content_cb" parameter of an LWP::UserAgent object and using the callback to calculate the progress.

Replies are listed 'Best First'.
Re: Tk::ProgressBar + LWP
by SuicideJunkie (Vicar) on Jul 03, 2013 at 22:10 UTC

    I've mixed threads and TK(x) before. Let me pull up the script...

    use warnings; use strict; use Storable; use Storable qw(nstore retrieve); use threads; use threads::shared; use Data::Dumper; use Mozilla::CA; use LWP::UserAgent; use HTTP::Cookies; use XML::Tiny; use YAML qw(DumpFile LoadFile); use Tkx; Tkx::package_require("tile"); use constant DebugTrace => 0; my @defaultFG = (-fg=>'#509AC8'); my @defaultBG = (-bg=>'#142029'); my @defaultBBG = (-bg=>'#0C1319'); my %statusColors = (Idle => '#008000', Ready => '#808000', Processing => '#FF8000', 'On Hold' => '#FF0000', 'Invalid Game' => '#808080', 'Invalid Mod' => '#808080', default=>'#FFFFFF'); my @gameListRows = (); my $sharedVars = {}; share($sharedVars); $sharedVars->{status} = 'Initializing Autohost'; my $infohash = {}; share($infohash); $sharedVars->{gameInfo} = $infohash; # Global gui elements my $mw; my $gameListFrame; my $statusLabel; # Global PBW's filesize restriction my $maxFileSize = 20e6; $|=1; # Init gui or die, before starting the processing thread. initGUI() or die "Can't initialize GUI\n"; # Processing thread will clear this if it starts successfully. $sharedVars->{fatalReason} = 'Processing thread failed to initialize'; # Fire and forget the processing thread my $pthread = threads->new(\&processingThread); $pthread->detach(); # Sleep to give processing thread time to start and clear fatalReason sleep 2; # Do the gui updateGameRows(); Tkx::MainLoop();

    So, what I did there was:

    1. Set up all shared variables
    2. Create the basic window and elements
    3. Spawn a child thread to do whatever and update the shared vars
    4. Use the parent to run the GUI, with a regular polling of the shared variables every 1/2 second.
    Just in case, I made the gui elements only touch local vars; there are local copies of the shared variables before looping over them and such.

    Warning: I'm not sure how safe all that really is, but I've been using it in a non-critical app with a very low rate of change for the shared values. It hasn't yet crashed or done anything weird for the last 6 months. YMMV

Re: Tk::ProgressBar + LWP
by Loops (Curate) on Jul 03, 2013 at 21:59 UTC
Re: Tk::ProgressBar + LWP
by kcott (Archbishop) on Jul 03, 2013 at 22:43 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1042275]
Approved by Happy-the-monk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2024-04-23 14:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found