Threads

Discussion in 'Perl Misc' started by RBCS, Feb 24, 2006.

  1. RBCS

    RBCS Guest

    Hello

    Can someone tell me which module I should use to create tasks in windows
    where I can run certain work in it. I used POE module, but this library
    crashes when I load it with a lot of work and is not very happy with
    ActiveState perl.

    What do you recomend me?

    Roman
    RBCS, Feb 24, 2006
    #1
    1. Advertising

  2. RBCS

    zentara Guest

    On Fri, 24 Feb 2006 14:47:49 +0100, RBCS <> wrote:

    >Can someone tell me which module I should use to create tasks in windows
    >where I can run certain work in it. I used POE module, but this library
    >crashes when I load it with a lot of work and is not very happy with
    >ActiveState perl.
    >
    >What do you recomend me?
    >Roman


    I use linux, but, here is one option for you to consider.
    Everything is a thread on win32, so you could use threads.

    The only reason you would need to use threads, rather than
    a separate process, is if you want to share data between your
    threads and the main program. Otherwise you could just use
    Win32::process to spawn off your work.

    The thing about threads, is that in general( to be foolproof :) ),
    you need to create the threads before you create any objects
    in your main thread. This usually means creating a bank of threads
    at the beginning of the program, and putting them to sleep.
    You then wake them up, and feed them data, and let them work,
    let them go back to sleep when done.
    You can create objects in the thread code block, which will only
    be used in the thread, like LWP objects for net work.

    You can create them dynamically, or use Thread::Queue, but
    that is a little trickier.

    Here is an example using Tk, you can rip the Tk code out, to
    just get the basic thread code, but Tk gives an event-loop
    style, like POE.

    In the following example, I send the thread to the end of it's code
    block, using an goto statement( for various reasons ), but you could
    just as well use a return. For a thread to be properly terminated, it
    must reach the end of it's code block( return), and then be joined
    with the join command.
    You can share data with the thread 2 ways.
    1, thru shared variables, OR
    2, you can pass it args on creation ( like passing @_ to a sub),
    and get returned data when it is joined.
    ( like the return values from a sub)

    There are tons of examples for threads on groups.google.com.
    You really should say something about what sort of tasks you
    want to run in the threads, because there are many different
    styles and queue's which you can use.

    This runs on Windows. I have noticed that threads work alot better
    on WindowsXP, than on older versions like win95, or winME.
    Earlier windows versions bog down when there are huge numbers
    of shared variables.
    This script runs a bank of 3 worker threads. It passes some code
    to be run (example: date), then starts a counter.


    #!/usr/bin/perl
    use warnings;
    use strict;
    use threads;
    use threads::shared;

    #works on Windows

    my $data = shift || 'date'; #sample code to pass to thread

    # create the threads before anything is done in main
    # to avoid object thread safety problems

    my %shash;
    #share(%shash); #will work only for first level keys
    my %hash;
    my %workers;
    my $numworkers = 3;

    foreach my $dthread(1..$numworkers){
    share ($shash{$dthread}{'go'});
    share ($shash{$dthread}{'progress'});
    share ($shash{$dthread}{'timekey'}); #actual instance of the thread
    share ($shash{$dthread}{'frame_open'}); #open or close the frame
    share ($shash{$dthread}{'handle'});
    share ($shash{$dthread}{'data'});
    share ($shash{$dthread}{'pid'});
    share ($shash{$dthread}{'die'});

    $shash{$dthread}{'go'} = 0;
    $shash{$dthread}{'progress'} = 0;
    $shash{$dthread}{'timekey'} = 0;
    $shash{$dthread}{'frame_open'} = 0;
    $shash{$dthread}{'handle'} = 0;
    $shash{$dthread}{'data'} = $data;
    $shash{$dthread}{'pid'} = -1;
    $shash{$dthread}{'die'} = 0;
    $hash{$dthread}{'thread'} = threads->new(\&work,$dthread);
    }


    use Tk;
    use Tk::Dialog;

    my $mw = MainWindow->new(-background => 'gray50');

    my $lframe = $mw->Frame( -background => 'gray50',-borderwidth=>10 )
    ->pack(-side =>'left' ,-fill=>'y');
    my $rframe = $mw->Frame( -background => 'gray50',-borderwidth=>10 )
    ->pack(-side =>'right',-fill =>'both' );

    my %actives = (); #hash to hold reusable numbered widgets used for
    downloads
    my @ready = (); #array to hold markers indicating activity is needed

    #make 3 reusable downloader widget sets-------------------------
    foreach(1..$numworkers){
    push @ready, $_;
    #frames to hold indicator
    $actives{$_}{'frame'} = $rframe->Frame( -background => 'gray50' );

    $actives{$_}{'stopbut'} = $actives{$_}{'frame'}->Button(
    -text => "Stop Worker $_",
    -background => 'lightyellow',
    -command => sub { } )->pack( -side => 'left', -padx => 10 );

    $actives{$_}{'label1'} = $actives{$_}{'frame'} ->Label(
    -width => 3,
    -background => 'black',
    -foreground => 'lightgreen',
    -textvariable => \$shash{$_}{'progress'},
    )->pack( -side => 'left' );

    $actives{$_}{'label2'} = $actives{$_}{'frame'} ->Label(
    -width => 1,
    -text => '%',
    -background => 'black',
    -foreground => 'lightgreen',
    )->pack( -side => 'left' );


    $actives{$_}{'label3'} = $actives{$_}{'frame'} ->Label(
    -text => '',
    -background => 'black',
    -foreground => 'skyblue',
    )->pack( -side => 'left',-padx =>10 );

    }
    #--------------------------------------------------

    my $button = $lframe->Button(
    -text => 'Get a worker',
    -background => 'lightgreen',
    -command => sub { &get_a_worker(time) }
    )->pack( -side => 'top', -anchor => 'n', -fill=>'x', -pady =>
    20 );

    my $text = $rframe->Scrolled("Text",
    -scrollbars => 'ose',
    -background => 'black',
    -foreground => 'lightskyblue',
    )->pack(-side =>'top', -anchor =>'n');

    my $repeat;
    my $startbut;
    my $repeaton = 0;
    $startbut = $lframe->Button(
    -text => 'Start Test Count',
    -background => 'hotpink',
    -command => sub {
    my $count = 0;
    $startbut->configure( -state => 'disabled' );
    $repeat = $mw->repeat(
    100,
    sub {
    $count++;
    $text->insert( 'end', "$count\n" );
    $text->see('end');
    }
    );
    $repeaton = 1;
    })->pack( -side => 'top', -fill=>'x', -pady => 20);

    my $stoptbut = $lframe->Button(
    -text => 'Stop Count',
    -command => sub {
    $repeat->cancel;
    $repeaton = 0;
    $startbut->configure( -state => 'normal' );
    })->pack( -side => 'top',-anchor => 'n', -fill=>'x', -pady => 20 );

    my $exitbut = $lframe->Button(
    -text => 'Exit',
    -command => sub {

    foreach my $dthread(keys %hash){
    $shash{$dthread}{'die'} = 1;
    $hash{$dthread}{'thread'}->join
    }

    if ($repeaton) { $repeat->cancel }
    #foreach ( keys %downloads ) {
    # #$downloads{$_}{'repeater'}->cancel;
    #}
    # $mw->destroy;
    exit;
    })->pack( -side => 'top',-anchor => 'n', -fill=>'x', -pady => 20
    );


    #dialog to get file url---------------------
    my $dialog = $mw->Dialog(
    -background => 'lightyellow',
    -title => 'Get File',
    -buttons => [ "OK", "Cancel" ]
    );

    my $hostl = $dialog->add(
    'Label',
    -text => 'Enter File Url',
    -background => 'lightyellow'
    )->pack();

    my $hostd = $dialog->add(
    'Entry',
    -width => 100,
    -textvariable => '',
    -background => 'white'
    )->pack();

    $dialog->bind( '<Any-Enter>' => sub { $hostd->Tk::focus } );

    my $message = $mw->Dialog(
    -background => 'lightyellow',
    -title => 'ERROR',
    -buttons => [ "OK" ]
    );

    my $messagel = $message->add(
    'Label',
    -text => ' ',
    -background => 'hotpink'
    )->pack();

    $mw->repeat(10, sub{
    if(scalar @ready == $numworkers){return}

    foreach my $set(1..$numworkers){
    $actives{$set}{'label1'}->
    configure(-text =>\$shash{$set}{'progress'});

    if(($shash{$set}{'go'} == 0) and
    ($shash{$set}{'frame_open'} == 1))
    {
    my $timekey = $shash{$set}{'timekey'};
    $workers{ $timekey }{'frame'}->packForget;
    $shash{$set}{'frame_open'} = 0;
    push @ready, $workers{$timekey}{'setnum'};
    if((scalar @ready) == 3)
    { }
    $workers{$timekey} = ();
    delete $workers{$timekey};
    }
    }
    });

    $mw->MainLoop;
    ###################################################################

    sub get_a_worker {

    my $timekey = shift;

    $hostd->configure( -textvariable => \$data);
    if ( $dialog->Show() eq 'Cancel' ) { return }

    #----------------------------------------------
    #get an available frameset
    my $setnum;
    if($setnum = shift @ready){print "setnum->$setnum\n"}
    else{ print "no setnum available\n"; return}

    $workers{$timekey}{'setnum'} = $setnum;
    $shash{$setnum}{'timekey'} = $timekey;

    $workers{$timekey}{'frame'} = $actives{$setnum}{'frame'};
    $workers{$timekey}{'frame'}->pack(-side =>'bottom', -fill => 'both' );

    $workers{$timekey}{'stopbut'} = $actives{$setnum}{'stopbut'};
    $workers{$timekey}{'stopbut'}->configure(
    -command => sub {
    $workers{$timekey}{'frame'}->packForget;
    $shash{ $workers{$timekey}{'setnum'} }{'go'} = 0;
    $shash{ $workers{$timekey}{'setnum'} }{'frame_open'} = 0;
    push @ready, $workers{$timekey}{'setnum'};
    if((scalar @ready) == $numworkers)
    { }
    $workers{$timekey} = ();
    delete $workers{$timekey};
    });

    $workers{$timekey}{'label1'} = $actives{$setnum}{'label1'};
    $workers{$timekey}{'label1'}->configure(
    -textvariable => \$shash{$setnum}{'progress'},
    );

    $workers{$timekey}{'label2'} = $actives{$setnum}{'label2'};


    $workers{$timekey}{'label3'} = $actives{$setnum}{'label3'};
    $workers{$timekey}{'label3'}->configure(-text => $timekey);



    $shash{$setnum}{'go'} = 1;
    $shash{$setnum}{'frame_open'} = 1;
    #--------end of get_file sub--------------------------
    }

    ##################################################################
    sub work{
    my $dthread = shift;
    $|++;
    while(1){
    if($shash{$dthread}{'die'} == 1){ goto END };

    if ( $shash{$dthread}{'go'} == 1 ){

    eval( system( $shash{$dthread}{'data'} ) );

    foreach my $num (1..100){
    $shash{$dthread}{'progress'} = $num;
    print "\t" x $dthread,"$dthread->$num\n";
    select(undef,undef,undef, .5);
    if($shash{$dthread}{'go'} == 0){last}
    if($shash{$dthread}{'die'} == 1){ goto END };
    }

    $shash{$dthread}{'go'} = 0; #turn off self before returning
    }else
    { sleep 1 }
    }
    END:
    }
    #####################################################################






    --
    I'm not really a human, but I play one on earth.
    http://zentara.net/japh.html
    zentara, Feb 25, 2006
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Codemonkey
    Replies:
    1
    Views:
    409
    Ying-Shen Yu[MSFT]
    Oct 30, 2003
  2. yoda
    Replies:
    2
    Views:
    426
    =?utf-8?Q?Bj=C3=B6rn_Lindstr=C3=B6m?=
    Aug 1, 2005
  3. threads without threads

    , Aug 27, 2004, in forum: C Programming
    Replies:
    4
    Views:
    391
    William Ahern
    Aug 27, 2004
  4. Pedro Pinto

    Java Threads - Get running threads

    Pedro Pinto, Apr 8, 2008, in forum: Java
    Replies:
    2
    Views:
    1,419
    Arne Vajhøj
    Apr 9, 2008
  5. Une bévue
    Replies:
    0
    Views:
    138
    Une bévue
    Jun 14, 2006
Loading...

Share This Page