Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations John Tel on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Perl/Tk - refresh window 1

Status
Not open for further replies.

MoshiachNow

IS-IT--Management
Feb 6, 2002
1,851
IL
HI,

From mine main window I activate a systen xcopy on a 4GB folder.
While this is happening,the window is nor movable nor beeing refreshed.

If I can not keep it in focus while the heavy xcopy is running,can I at least keep it refreshed every 2 seconds?

Thanks

Long live king Moshiach !
 
If your program is being blocked by one command, it won't be very easy to update the main window while the command is going. You may need to use threads.

Perl/Tk doesn't work well with threads in my experience. What I tend to do is create a thread at the beginning of my program (before loading Tk) which awaits commands and executes them via a shared array.

Code:
#!/usr/bin/perl -w

use strict;
use warnings;
use threads;
use threads::shared;

# Create some shared variables
my @commands : shared; # incoming commands
my @output : shared;   # if you want the worker to give us some "feedback" of its progress

# Create the worker thread
my $worker = threads->create (sub {
   # Loop for new commands
   while (1) {
      sleep (undef,undef,undef,0.1); # sleep .1 seconds,
         # otherwise Perl will devour tons of CPU

      # If new commands are awaiting...
      if (scalar(@commands)) {
         # eval the latest one
         my $latest = shift(@commands);
         my $eval = eval ($latest) || $@;

         # give some feedback?
         push (@output,$eval);
      }
   }
});

# now load Tk
use Tk;

my $main = MainWindow->new;

# a test command
$main->Button (
   -text => 'Sleep 10 Seconds', # a major Perl blocker!
   -command => sub {
      # push this Perl code to commands
      push (@commands, 'sleep(10);');
   },
)->pack;

# if we want to track @updated, use a loop instead
# of MainLoop
while (1) {
   select (undef,undef,undef,0.1);
   $main->update;

   # if there are new outputs
   if (scalar(@output)) {
      # pop up the output in a dialog?
      $main->Dialog (
         -title => 'Thread Output',
         -text  => shift(@output),
         -buttons => [ 'OK' ],
      )->Show;
   }
}

That's a basic example to help you get started. Since threads run asynchronously with each other, it may be helpful for your worker thread to use a shared @output array as a way to tell your main thread that it finished running.
 
*sorry, typo

sleep (undef,undef,undef,0.1);

should be

select (undef,undef,undef,0.1);
 
Thanks,

All I wanted here ,actualy, was just to keep the main window on top of everything else,without much need to input more commands.

P.S.- instead of shared array I normally use a flag file,testing it's existence when needed.

Long live king Moshiach !
 
Well, there is this FAQ about fixing your unresponsive GUI when running long processes:


But it doesn't apply to your case. I'm assuming you're doing something along the lines of this?

Code:
$main->Button (
   -text => 'Click Me!',
   -command => sub {
      system ("xcopy .......");
   },
)->pack;

And that the system command is blocking until xcopy finishes its process. In this case, it doesn't give you a chance to run any Tk commands, because system doesn't return until its commands are completed. So there's not an easy solution to stop your GUI from freezing up while xcopy is running, without some form of threading or forking or otherwise making xcopy run in a different process than your GUI.

And with threading, the situation gets more complicated because Perl/Tk likes to treat threads special, and I haven't found any info on what it wants from them. But spawning a new thread after loading the Tk library tends to crash Perl, so the threads need to be created before you load Tk, which makes it more difficult because then it needs to await commands.

Otherwise you could've done:
Code:
-command => sub {
   threads->create (sub {
      system ("xcopy ...");
   })->detach;
},

But PerlTk doesn't like that usage of threads in my experience.
 
If you don't see the point of all of this, let's go back to your first question:

If I can not keep it in focus while the heavy xcopy is running,can I at least keep it refreshed every 2 seconds?

To refresh it on any timed interval requires Perl to update() the windows (or DoOneEvent() as that other FAQ said, which is basically the same thing). So if Perl is blocked by xcopy for, say, 60 seconds... it has no opportunity to run any additional Perl code to update the MainWindow until xcopy has finished, so you can't program any intervals to update the window.

The best you can do is keep the window focused and, before launching the command, tell your user to be patient, as the window WILL freeze up until the command is finished, and the best you can do is avoid your users freaking out thinking the program is frozen.

Otherwise, thread it.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top