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

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

Hello monks, I am in need of thine expert advice.

Situation:

-I am creating a Tkx GUI.

-This Tkx GUI runs a batch file when I press a button.

-While running the batch file I want the GUI to still be there but buttons are disabled. Additionally, I want a progress bar (indeterminate is fine) running while the batch file is running.

-I also want the output of the batch file to be displayed continuously, like it normally does when you run it by clicking.

-After the batch file finishes running, I want the GUI to be enabled again and do other stuff with other buttons

Things to note:

- The batch file executes quite a long time.

- Running this batch file normally will show a log that updates what it's doing, I need to see this too.

- I can not edit the batch file.

What I've tried:

- Using "exec", the perl gui calls a separate batch file - that calls the correct batch file - and subsequently call the GUI again after the batch is finished (so : GUI -> batch -> GUI)

I can technically get what I want using this method but it doesn't feel like a good design.

Any thoughts?

Thanks!

  • Comment on Run a batch file and wait for it to finish

Replies are listed 'Best First'.
Re: Run a batch file and wait for it to finish
by roboticus (Chancellor) on May 07, 2014 at 11:09 UTC

    rezelle008:

    Try using fork and waitpid in addition to exec. It should be something like:

    # Program execution splits here: if ($kidPID=fork()) { # On return from fork, the parent is in this branch of the if stat +ement do { # Keep checking for child process to end. (Probably ought to +put in # a sleep so we don't just sit and pound the CPU while we're w +aiting) $kidPID = waitpid($kidPID, WNOHANG); } while $kidPID > 0; # Child is done now, so continue onwards } else { # On return from fork, the child process is in this branch exec($your_batch_file); }

    Note: I've not done this, nor tested the above code, but it should be pretty close. Also, you may want to modify the logic a bit so that you don't hang the GUI thread. Instead, you could display a timer showing how long the process has been running, and if you want to get fancy, you could even provide a button to terminate the batch job or some such.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

Re: Run a batch file and wait for it to finish
by jellisii2 (Hermit) on May 07, 2014 at 12:37 UTC

    use strict; use warnings; use Tkx; use threads; # ... set up your controls $bar->configure( -orient => "horizontal", -mode => "indeterminate", ); $bar->start(); my $thread = threads->create(sub { system("my.bat"); }); $thread->set_thread_exit_only(1); while ($thread->is_running()) { Tkx::update(); } $progress_bar->stop();

    I use basically this code to launch an editor so the user can easily alter the configuration file for my program. The new thread allows Tkx to continue to update while waiting for the user to close the editor window. Depending on what you're doing before you launch your thread, you may not be able to join the thread properly. I leave the thread unjoined and ignore the warnings when my program exits, but it's never executing a ton of stuff this way.

    There are probably better ways to manage the thread and what it's executing, but I haven't had time to research it. Leaving the thread unjoined doesn't impact me significantly, as the program I'm doing that on exits on completion. The UI is just for the end user to be able to select some files and feed some data in before the process starts.

Re: Run a batch file and wait for it to finish
by Anonymous Monk on May 07, 2014 at 11:12 UTC
Re: Run a batch file and wait for it to finish
by rezeile008 (Sexton) on May 08, 2014 at 03:48 UTC
    Thanks a lot for the replies! You have pointed me to the right direction and now I have found my way to the Fork VS Thread topics. :D
      It's my understanding that fork in Windows has to be compiled in, as opposed to threads.

      From perlfork:

      On some platforms such as Windows where the fork() system call is not available, Perl can be built to emulate fork() at the interpreter level. While the emulation is designed to be as compatible as possible with the real fork() at the level of the Perl program, there are certain important differences that stem from the fact that all the pseudo child "processes" created this way live in the same real process as far as the operating system is concerned.

      For what you're doing it may not make a difference, assuming it's compiled in, but I bring it up because it could at some point down the road.