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
