Ok, thanks.

I've finally used

Wx::SafeYield($Window);

in the loop, and now the window is just a little bit more responsive.

Octavian

  ----- Original Message ----- 
  From: Mike Schroeder 
  To: Octavian Rasnita ; [email protected] 
  Sent: Sunday, February 10, 2008 6:34 PM
  Subject: Re: using a progress bar with POE::Loop::Wx


  Using POE is not something you do for just one thing, it affects the whole 
way you would code your app, so you would use POE to do non-blocking file 
transfer (using something like POE::Component::Client::FTP), and use POE to do 
non-blocking DBI updates (using something like POE::Component::SimpleDBI).  It 
doesn't really work to use POE for just one thing in your app -- to take 
advantage of POE, you either embrace it for everything or don't use it at all.  
YMMV.



  On 2/10/08, Octavian Rasnita <[EMAIL PROTECTED]> wrote:
    Hi Mark,

    Thank you for your help and for some clarifications.
    I didn't know that cooperative multitasking doesn't imply multithreading.

    But in this case I am not sure that POE can help me to do what I want. The 
ProgressDialog is not responsive not because updating the progress bar takes 
much processor time, but because the file download and database updates does 
that.

    If POE can't do the file upload and the database update in a separate 
thread but in the main thread, the one that manages the GUI, then the GUI will 
be unresponsive.

    The file upload and database update are continuous tasks, and I cannot put 
a subroutine to do something from 5 to 5 seconds in order to do the file 
download, and now I do something like:

    <create the ProgressDialog window>

    <while downloading the file>
    <save the current buffer to the hard disk>
    <update the ProgressDialog window>
    <end the file download>

    <close the ProgressDialog window>

    Well, with POE I can update the ProgressDialog separately, but until the 
file finishes to download, the current window of the program will be 
unresponsive.

    With Win32::GUI I can insert the following line in the loop, and then the 
GUI will be much responsive, but I don't know if there is such a thing in 
WxPerl:

    Win32::GUI::DoEvents() >= 0 or die "Window was closed during processing";

    Do you know by chance if there is a method that makes WxPerl to handle the 
events in the queue before passing to the next step in the loop?

    Thank you.

    Octavian

      ----- Original Message ----- 
      From: Mike Schroeder 
      To: Octavian Rasnita 
      Sent: Saturday, February 09, 2008 9:00 PM
      Subject: Re: using a progress bar with POE::Loop::Wx


      First, with POE, I don't think this would be another thread.  POE uses 
cooperative multi-tasking, not threads.

      We use two different approaches -- polling a remote job for its progress, 
and reacting to local events.

      In our case, we made a Panel that holds the Gauge and some StaticText 
controls to display extra info.

      The Panel in turn has a "StartPolling" method which starts off a POE 
event to fetch remote job data, and calls itself again every 5 seconds until 
the job is complete.  Here is some stripped down psuedo code:


      sub StartPolling {
         # Gather Args
         # Start a POE event to GetData (results will go to ReceiveData)
         # delay_set('StartPolling', 5);
      }



      Depending on how abstracted your environment is, you may have POE stuff 
in here or not.  In our case, we don't.

      The Panel also has a "ReceiveData" method which either receives the data 
from the polling events, *or* can receive data directly from a local event.  
Here is some code again -- hopefully it makes sense :)


      sub ReceiveData {
         my ( $self, $data )  = @_;

         Wx::LogVerbose("Progress ReceiveData: $self " . Dumper $data );

         unless ( $self->{_first_data} ) {
            $self->{progress_gauge}->SetRange( $data->{expected} );
            $self->{_first_data} = 1;
         }

         if ( $data->{status} eq 'C' ) {
            Wx::LogVerbose("Job $data->{job_id} is Complete");
            # job is done
            $self->_update_data( $data );
            if ( ref $self->{_on_complete} eq 'CODE' ) {
               &{ $self->{_on_complete} } (
                                 DATA    => $data,
                                 CONTROL => $self,
                                 FRAME   => $self->GetTopLevelParent()
                                 );
            }

            if ( $self->{_close_on_complete} ) {
               $self->GetTopLevelParent()->Close();
            } else {
               # stop polling - happens automatically when frame closed
               $self->GetTopLevelParent()->unregister_control(
                        cachekey => $self->{_cache_key},
                        control  => $self );
            }
         } elsif ( $data->{status} eq 'R' ) {
            Wx::LogVerbose("Job $data->{job_id} is Running");
            # job is running
            $self->_update_data( $data );
         } else {
            Wx::LogVerbose("Unknown Job Status!!! " . Dumper $data);
         }
      }

      sub _update_data {
         my ( $self, $data )  = @_;

         # Update gauge
         $self->{progress_gauge}->SetValue( $data->{current_count} );

         # Update Labels
         $self->{progress_title}->SetLabel( "Job " . $data->{job_id} . ' - ' .
                                 $data->{description} );
         $self->{expected}->SetLabel( $data->{expected} );
         $self->{current}->SetLabel( $data->{current_count} );
         $self->{remaining}->SetLabel( $data->{current_rate} . ' per ' .
                                          $data->{rate_unit} );
         $self->{start_time}->SetLabel( $data->{start_time} );
         $self->{eta}->SetLabel( $data->{eta_time} );
         $self->{elapsed}->SetLabel( $data->{duration} );

      }


      So every time your file download receives another chunk, it should send 
an event over to ReceiveData, which will _update_data() the Gauge and 
StaticText controls.

      Hopefully this at least gives you some ideas...

      Mike.



      On 2/9/08, Octavian Rasnita <[EMAIL PROTECTED]> wrote: 
        Hi,

        I want to use a ProgressDialog to show the progress of a file download 
and
        database update.
        The progress works well, however the ProgressDialog window is very
        unresponsive because the program uses a single thread.

        Is it possible to use POE::Loop::Wx for making the dialog window more
        responsive?
        Or is there another better method for doing this?

        In the POE::Loop::Wx examples I've seen that it can be used for making
        asynchronious requests, but those requests were made automaticly, after 
a
        certain number of seconds which were defined in the POE::Session. The
        requests that were made at a certain command (a button click) were made 
in
        the main thread of the program.

        I need to run the subroutine that does the ProgressDialog update with 
some
        parameters and only after a certain part of the file was downloaded or a
        certain number of records were inserted in the database.

        Please tell me if I can find an example of using a progress bar that 
uses a
        separate thread for doing this.

        Or if it is better to use the main thread for update the ProgressDialog 
and
        a second thread for doing the file download and database update, please 
give
        me some hints about how to do that with POE::Loop::Wx or another method 
that
        can allow the 2 threads to communicate.

        Thank you.

        Octavian





      -- 
      Mike Schroeder
      [EMAIL PROTECTED]
      877-751-3300 x401 



  -- 
  Mike Schroeder
  [EMAIL PROTECTED]
  877-751-3300 x401 

Reply via email to