http://qs321.pair.com?node_id=124760


in reply to Re:(wog) Win32::Gui + Threading?
in thread Win32::Gui + Threading?

I thought this task would be relatively easy. Basically, you'd fork off a "server" at the beginning of your script which would have a channel to your script, probably created with pipe. You'd send URLs to get over a pipe, and the other end would read them, fetch the URL, and return the URL over another pipe. (This scheme would basically be what is done under "Bidirectional Communication with Yourself" in perlipc.)

Unfortunately, Win32::GUI makes watching for the response difficult. Under Tk, one can watch for "fileevents" and thus get notified when data is available on a filehandle (from Tk's main loop.) Win32::GUI does not have a generic filehandle watching mechanism. One could probably emulate it using Win32::GUI::Timer and non-blocking I/O:

Basically, you'd periodically poll the pipe going into your script to see if it has data for you. So regularly, you'd try to sysread from your pipe which has been set non-blocking (so your GUI won't freeze). (update: You'd probably schedule these read attempts with Win32::GUI::Timer, of course.) I reccommend sysread, because you're probably going to need to do your own I/O buffering this case. You probably want a relatively short time interval, something to balance use of CPU with apparent speed. To enable non-blocking I/O, you'd use IO::Handle's blocking method with an argument of 0. To check for data from the socket, you'd read it (with sysread) and see if you got an error (undef return). If you got an error and $! was EAGAIN (see the Errno module), then there is no data on the pipe. If $! wasn't EAGAIN, but there was an error, then you'd probably want to die, because something weird would've happened. If you don't get an error, you can add that to your cache of the results (note that you probably won't get all such data at once). (You probably want to have some way of marking when the end of data is, possibly just prefixing data you send with the length of the data.)

Personally, I'd prefer a solution where Win32::GUI was modified to support watching filehandles.

update: I forewarn that this advice is untested. (Also updated phrasing slightly.)

Replies are listed 'Best First'.
Re: Re: Re:(wog) Win32::Gui + Threading?
by Flame (Deacon) on Nov 12, 2001 at 18:24 UTC
    This can make things more interesting... I can loop within another subroutine containing DoEvents() to keep the GUI alive... It could do that while waiting for something to come over the pipe?

    I just happened to see the command in the docs just now... I'm not quite sure HOW to do what I just tried to describe though.

    Perhaps this can be combined with Tk's monitoring capability?


    -----BEGIN GEEK CODE BLOCK-----
    Version: 3.12
    GIT d- s:++ a--- C++++ UL P+++>++++ L+ E- W++>+++ N !o K- w+ O---- M-- V--
    PS PE Y- PGP t++(+++) 5(+++)++++ X R+@ tv+ b+++ DI+ D- G e->+++ h! r-- y-
    ------END GEEK CODE BLOCK------
    Translate

    "Weird things happen, get used to it."

    Flame ~ Lead Programmer: GMS

Re: Re: Re:(wog) Win32::Gui + Threading?
by Flame (Deacon) on Nov 12, 2001 at 18:00 UTC
    Wow... thats a lot to go through, especially since I'm not familiar with many of those commands. *Pulls out Programming Perl R3*

    Thanks, this looks promising.


    -----BEGIN GEEK CODE BLOCK-----
    Version: 3.12
    GIT d- s:++ a--- C++++ UL P+++>++++ L+ E- W++>+++ N !o K- w+ O---- M-- V--
    PS PE Y- PGP t++(+++) 5(+++)++++ X R+@ tv+ b+++ DI+ D- G e->+++ h! r-- y-
    ------END GEEK CODE BLOCK------
    Translate

    "Weird things happen, get used to it."

    Flame ~ Lead Programmer: GMS

Re: Re: Re:(wog) Win32::Gui + Threading?
by Flame (Deacon) on Nov 13, 2001 at 03:29 UTC
    Oh, another question... how do I force a forked process to exit when the main program does?




    -----BEGIN GEEK CODE BLOCK-----
    Version: 3.12
    GIT d- s:++ a--- C++++ UL P+++>++++ L+ E- W++>+++ N !o K- w+ O---- M-- V--
    PS PE Y- PGP t++(+++) 5(+++)++++ X R+@ tv+ b+++ DI+ D- G e->+++ h! r-- y-
    ------END GEEK CODE BLOCK------
    Translate

    "Weird things happen, get used to it."

    Flame ~ Lead Programmer: GMS

      What you probably should do is send a "special" message to the forked process (like you would send URLs, etc.) that will cause it to exit.
        I've tried this (based upon several examples... I really still don't understand what most of this is doing...):
        pipe(FROM_P, TO_C) or die "pipe: $!"; select(((select(TO_C), $| = 1))[0]); if (!(my $pid = fork)){ close(TO_C); #close(FROM_C); my $running = 1; while(my $line = <FROM_P>) { Win32::GUI::MessageBox(0,"Child Pid $$ just read this: $line","G +MS Alert"); chomp($line) if($line =~ m/\n$/o); if(lc($line) eq 'exit'){ Win32::GUI::MessageBox(0,"Exit","GMS"); sleep(20); #To allow time to read the MessageBox... if it eve +r comes up... exit; } } }


        Later on, these two subs deal with the exiting of the main program:
        sub GMSMain_Terminate { defined(my $win = $Win32::GUI::Loft::window{GMSMain}) or return(1); print TO_C 'exit'; return(-1); } sub mnuFileExit_Click { defined(my $win = $Win32::GUI::Loft::window{GMSMain}) or return(1); print TO_C 'exit'; return(-1); }


        When running it, however, I can exit part of it (the gui part) but it remains visible and perl itself keeps running. There is no message box popping up from the other process either.

        I'm probably making a rather stupid mistake, so please point it out if I am.


        -----BEGIN GEEK CODE BLOCK-----
        Version: 3.12
        GIT d- s:++ a--- C++++ UL P+++>++++ L+ E- W++>+++ N !o K- w+ O---- M-- V--
        PS PE Y- PGP t++(+++) 5(+++)++++ X R+@ tv+ b+++ DI+ D- G e->+++ h! r-- y-
        ------END GEEK CODE BLOCK------
        Translate

        "Weird things happen, get used to it."

        Flame ~ Lead Programmer: GMS