[Gambas-user] App idle with long loops
Tobias Boege
taboege at ...626...
Sun Oct 9 18:40:28 CEST 2016
On Sun, 09 Oct 2016, Jorge Carrión wrote:
> 2016-10-08 23:54 GMT+02:00 Demosthenes Koptsis <demosthenesk at ...626...>:
>
> > On 8/10/2016 19:09 μμ, Tobias Boege wrote:
> > > On Sat, 08 Oct 2016, Demosthenes Koptsis wrote:
> > >> Hello,
> > >>
> > >> i have very long (time consuming) For loops and my app is frozen until
> > >> loop is finished.
> > >>
> > >> for example i wget urls with a custom Sub which Shell("wgetURLS.sh") To
> > >> sOUTPUT
> > >>
> > >> 'get urls
> > >> For i = 0 To iDepth
> > >> wgetURLS(i * 10)
> > >> Next
> > >>
> > >> Public Sub wgetURLS(iStart As Integer)
> > >> .....
> > >>
> > >> Shell("wgetURLS.sh") To sOUTPUT
> > >>
> > >> .....
> > >>
> > >> --------------
> > >>
> > >> Is there possible to set the gui idle and the same time run For...loops?
> > >>
> > > If you only want to refresh the GUI (e.g. if your For loops update a
> > > ProgressBar on your form and you want to update the value of that bar
> > > during the loop), then Wait [1] is sufficient.
> > >
> > > If you want the GUI to be fully operatable while your loops run in the
> > > background, you have to use a background Task [2]. As Gambas is single-
> > > threaded, Tasks are implemented as external processes which execute one
> > > of your classes. This limits the things you can do with Tasks (you cannot
> > > directly modify the main program, for example, but have to send data and
> > > status reports through a pipe from your Task to the main process and
> > > interpret them there). However, if all you want is loading some files via
> > > wget, that should not be a problem.
> > >
> > > Of course, there is also the gb.net.curl component which can download
> > files
> > > asynchronously. If you can use that (which depends on what you want to
> > do),
> > > you should.
> > >
> > > And as a fourth option, looking further into your code: if you want to
> > > execute shell scripts in a For loop, then don't use the Shell-To syntax
> > > but create a Process object instead and accumulate its output in Read
> > > events. The event loop will take care of everything and the GUI will be
> > > usable without any extra effort on your side.
> > >
> > > Finding the best solution depends, who would have thought, on what you
> > want
> > > to do *specifically*. Tasks are the most general and most cumbersome
> > option.
> > >
> > > Regards,
> > > Tobi
> > >
> > > [1] http://gambaswiki.org/wiki/lang/wait
> > > [2] http://gambaswiki.org/wiki/comp/gb/task
> > >
> > Thanks very much for the details.
> >
> > Regards,
> >
> > Dim
> >
> >
> Is there any example of task fork use? I have a proyect who sending massive
> e-mails to our customers and I guess that task can be a good solution...
>
> Regards
>
It normally works like this:
- You write a dedicated class, let's call it MyTask, to perform your task.
This class must inherit the Task class.
- The constructor of MyTask can receive some arguments for the task, like
an array of recipient addresses and bodies for your batch email.
- After the MyTask object is created, the process fork is postponed to the
next invocation of the event loop. You may want to keep this in mind if
you sometimes start a whole bunch of tasks at once or if you want to
wait for the results of your task in the current procedure. To have the
tasks started, you either have to enter the event loop, either by
rolling up the current code path or by calling Wait.
- The interpreter will then fork and jump into the Main() method of the
MyTask object. The standard output of the new process running the Task
is redirected into the main program and raises Read events of the Task
object. You can also return serialisable data from the Main() method
which is transferred into the main process and which you can fetch these
using MyTask.Value.
- Because returning a single value at the end of the task may not be
sufficient, you normally end up using the standard output to communicate
more regularly with the main process. I could imagine that you want to
send messages of the form:
"sent\tx\tn"
to your main process, indicating that you just sent the x-th email of
n emails total. The main process intercepts this string, has to parse it
and can then update a ProcessBar or something. This is the way I use
Tasks in my projects, anyway.
An example can also be found in the gb.form component. The FileView class
uses a background task named CTaskPreview to make preview of images in the
background and send them to the main process once they're ready.
Regards,
Tobi
--
"There's an old saying: Don't change anything... ever!" -- Mr. Monk
More information about the User
mailing list