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

I have a Perl/Tk program running under Windows that wants to spawn a copy of excel. Running `start file.csv` with backticks is usually the easiest way to do it, but with the Tk event loop running there's always a 30 second delay until the subprocess starts up. Task manager doesn't show any activity on the computer's part, and the backticks run quite snappily outside of Tk.

Anybody seen this before or have any ideas?

Here's a demo script. Use the menu option File/Report extract to see the pause. (Note that the window it opens is tiny, you might miss it on your screen).

use Tk; use File::Spec; $top = MainWindow->new(); my $menubar = $top->Menu(-type => 'menubar'); $top->configure(-menu => $menubar); my $filemenu = $menubar->cascade(-label => '~File', -tearoff => 0); $filemenu->command(-label => '~Report extract', -command => [\&report_extract], ); $filemenu->command(-label => 'E~xit', -command => [sub {exit}], ); print STDERR "there's a tiny window open, it's small but it's there\n" +; MainLoop(); sub report_extract { my $tmpdir = File::Spec->tmpdir(); open (F, ">$tmpdir\\xx.csv") || die $!; print F "aaa,bbb,ccc\nddd,eee,fff\n"; close F; my $cmd = "start $tmpdir\\xx.csv"; print STDERR "running $cmd\n"; `$cmd`; }

Replies are listed 'Best First'.
Re: subprocess delay on Windows with Perl/Tk
by Fletch (Bishop) on Jun 03, 2004 at 18:26 UTC

    Backticks are for capturing the output from something (and hence will wait until the child returns before continuing). You probably want to look at one of the Win32::* modules (Win32::Process maybe) and use that instead (or system and/or fork/exec on a real OS).

      Thanks. Win32::Process works, but I'd have to know the full path to excel.exe. "start" lets the file type registry on the client pc take care of finding excel ("start" also takes care of forking and returns immediatly, the Tk program doesn't have to wait for excel to exit, although in this case *everthing* is waiting for excel to *start*).

      Backticks with `start file.csv` work fine as long as the Tk event loop isn't running. I'd still like to hear if anyone else has the same problem.

        Win32::Process works, but I'd have to know the full path to excel.exe.

        That's not hard to find.

        use File::Spec; sub find_in_path { my $prog = shift; my $fmm; for my $d (File::Spec->path()) { $fnm = File::Spec->catfile($d,$prog); last if -x fnm; $fnm = undef; } return $fnm; } my $excel = find_in_path('excel.exe');
        90% of every Perl application is already written.
        dragonchild
        If that's a problem for you, then use system or fork/exec.

        MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
        I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
        ** The third rule of perl club is a statement of fact: pod is sexy.

Re: subprocess delay on Windows with Perl/Tk
by NetWallah (Canon) on Jun 03, 2004 at 23:14 UTC
    Here is a version that runs just fine on Windows XP ... using threads.
    use strict; use Tk; use File::Spec; use threads; use Thread::Queue; my $RequestQ = Thread::Queue->new; my $worker = threads->new(\&worker); my $top = MainWindow->new(); my $menubar = $top->Menu(-type => 'menubar'); $top->configure(-menu => $menubar); my $filemenu = $menubar->cascade(-label => '~File', -tearoff => 0); $filemenu->command(-label => '~Report extract', -command => [\&report_extract], ); $filemenu->command(-label => 'E~xit', -command => [\&Shutdown], ); print STDERR "there's a tiny window open, it's small but it's there\n" +; MainLoop(); print STDERR "Exit Main loop \n"; ############################ sub Shutdown{ $RequestQ->enqueue(undef); # quit the worker $worker->join; print STDERR "FINISHED Shutdown\n"; exit; # Clean up Tk } ############################ sub report_extract { my $tmpdir = File::Spec->tmpdir(); open (F, ">$tmpdir\\xx.csv") || die $!; print F "aaa,bbb,ccc\nddd,eee,fff\n"; close F; my $cmd = "start $tmpdir\\xx.csv"; print STDERR "running $cmd\n"; $RequestQ->enqueue($cmd); } ################## sub worker{ while (my $target = $RequestQ->dequeue){ print STDERR "Request $target Read\n"; system $target; print STDERR "Finished target\n"; } print STDERR "Thread exit\n"; }

    Offense, like beauty, is in the eye of the beholder, and a fantasy.
    By guaranteeing freedom of expression, the First Amendment also guarantees offense.

      Oooh! Now that's fancy. I like it. What was the train of thought that led you to consider threads as a solution? It never would have occurred to me.
        I had always found "fork" non-intutive, and a pain (on Win32), because you needed a mechanism to exchange data between parent and child - the working ones are complicated (to my simple mind).

        I had tested perl threads on Win32 and found that to be robust, intutive and, to my twisted brain, very logical.

        The thread queue model rules!!

        I had never tried using threads with Tk - so I enjoyed playing with your code.
        Cheers.

        Offense, like beauty, is in the eye of the beholder, and a fantasy.
        By guaranteeing freedom of expression, the First Amendment also guarantees offense.