https://foro.gambas-es.org/viewtopic.php?f=5&t=6396
-----------------------------------
shordi
Martes, 23 May 2017, 20:20

Simulando La Programación Con Hilos O "Programas Preñados"
-----------------------------------
Perdón por el título, pero es que no sé muy bién cómo titular ésto que ahora os presento.

Todos sabemos que gambas no soporta la programación por hilos, todo se maneja en un único proceso en ejecución y punto.
Esto ocasiona que no sea posible ejecutar cosas en segundo plano y que si tenemos tareas que tarden mucho, la aplicación quede como colgada hasta que finalice la tarea que la bloquea. El ejemplo más típico de ésto sería un backup o una descarga/subida de ficheros desde/a internet.

¿Cómo conseguir que ésta tarea se haga de manera que no paralice el programa principal? Hay muchas formas, pero yo ahora os presento ésta que me he inventado: "Los Programas Preñados".

Un ejemplo:
Cread un proyecto de consola nuevo y en el módulo principal ponéis éste código.
[code linenumbers=false syntax=gambas]Public Sub Main()
  
  Dim carpeta As String

  carpeta = User.Home &/ "Escritorio/borrame" 'normalmente esta sería una carpeta oculta en el home del usuario con los archivos de configuración del programa 
  If Not Exist(carpeta) Then Return 
  Sleep 3 'aquí paramos tres segundos esto simula una tarea que lleve mucho tiempo, como un backup o algo así
  File.Save(carpeta &/ Format(Now(), "yyyy-mm-dd hh:nn:ss"), "Hola mundo")
 
End[/code]
Este códio sólo espera durante 3 segundos y luego guarda un fichero en la carpeta indicada con la hora como nombre de fichero. Nada más.
Donde esperamos 3 segundos, se supone que iría la llamada al código que tarda mucho, (descargas, backups, etc.)

Ahora cread otro proyecto gráfico nuevo, en el ejemplo que os adjunto lo he llamado "hilandero" por aquello de programación por hilos...  :oops: 
Este proyecto lo enlazáis con el componente gb.inotify, en el está el control watch.
Estos son los componentes mínimos necesarios (puede ser otra librería gráfica que no sea qt, claro)
 [img]https://foro.gambas-es.org/files/images/38/captura_de_pantalla_de_2017_05_23_20_44_58.png[/img] 
Cerramos el proyecto hilandero, volvemos al proyecto de consola (en el ejemplo lo he llamado "segundoplano") y entramos en la opción del menú Proyecto->Crear->Ejecutable
Cuando nos pide en qué carpeta creamos el ejecutable, en lugar de seleccionar la carpeta del proyecto "segundoplano", seleccionaremos la del otro proyecto "hilandero". Es decir, incrustamos el ejecutable en el otro proyecto (de ahí lo de "preñado"). 
Cerramos el proyecto segundoplano, que ya no nos hace falta y volvemos a abrir el Hilandero.
Notaréis que en el panel izquierdo no aparece el archivo que acabamos de copiar. Eso se debe a que el IDE discrimina los archivos con extensión .gambas y no los muestra (por eso cuando creáis un ejecutable de un proyecto no lo veis en el panel), pero tranquilos que está ahí.

Ahora en el formulario principal, para el ejemplo, añadimos dos botones, dos timer, y dos textAreas. Con éste aspecto:
 [img]https://foro.gambas-es.org/files/images/38/captura_de_pantalla_de_2017_05_23_20_56_20.png[/img] 
y este código:
[code linenumbers=false syntax=gambas]
Private w As Watch
Private carpeta As String
Private veces As Integer

Public Sub Form_Open()

  carpeta = User.home &/ "Escritorio/borrame" 'normalmente ésta sería una carpeta oculta en el home del usuario con el nombre del programa o algo así.
  If Not Exist(carpeta) Then Mkdir carpeta
  If Not Exist(carpeta &/ "segundoplano.gambas") Then 
    Copy "segundoplano.gambas" To carpeta &/ "segundoplano.gambas" 'extraemos el hijo. Este sería el parto jejeje
    Shell "chmod +x " & carpeta &/ "segundoplano.gambas"
  Endif
   w = New Watch(carpeta) As "lacarpeta" 'ponemos el watch a vigiliar y lo llamamos lacarpeta

End

Public Sub Button1_Click()


  veces = 0
  Timer1.Start
  
End

Public Sub lacarpeta_Create() 'esto se ejecuta cada vez que se crea  un fichero en lacarpeta
  
  TextArea1.Text &= gb.NewLine & "Tarea realizada a las " & Format(Now(), "hh-nn-ss")  
  
End


Public Sub Timer1_Timer()

  Shell "/usr/bin/gbr3 " & carpeta &/ "segundoplano.gambas "   'aquí lanzamos el segundoplano
  Inc veces
  If veces > 4 Then Timer1.stop

End


Public Sub Form_Close()

  w.Pause()
  w = Null

End


Public Sub Button2_Click()

  veces = 0
  Timer2.Start
  
End

Public Sub tarea()

  Sleep 3                               ''aquí paramos tres segundos
  File.Save(carpeta &/ Format(Now(), "yyyy-mm-dd hh:nn:ss"), "Hola mundo")

End

Public Sub Timer2_Timer()

  tarea()
  Inc veces
  If veces > 4 Then Timer2.Stop  

End
[/code]

Al abrir el fMain, ponemos un objeto watch, llamado w en el ejemplo, que "vigila" la carpeta donde se crean los ficheros y levanta el evento lacarpeta_create() cuando se crea un fichero en ella. (Este evento nos informa de que se ha ejectuado la tarea en uno de los textareas)
Un botón pone en marcha uno de los timer que ejecuta la misma tarea que el proyecto segundoplano (sleep 3 y grabar fichero en la carpeta) dese el propio formulario Main.

El otro botón pone en marcha el otro timer que lanza desde una shell el programa segundoplano que ejecuta la tarea (sleep3 y grabar fichero).

La idea es que pulséis uno de los botones y a continuación en el segundo textarea escribáis sin parar (basta con mantener pulsada una tecla de una letra). Podréis ver la diferencia  mientras se va ejectuando la tarea cinco veces.

La ventaja de la técnica es que al ir incrustado el proyecto hijo dentro del padre, se incluye dentro del ejecutable padre y a la hora de crear el paquete de instalación y distribuir vuestro programa, todo aparenta ser un proyecto monolítico y normal.
Por otra parte si construis bien los sub_proyectos, son una forma magnífica de reutilizar código de un proyecto a otro por ejemplo con las rutinas de backup.

Os adjunto un comprimido con el fuente de los dos proyectos padre-hijo.

Espero que os sea útil.

Saludos


-----------------------------------
shordi
Martes, 23 May 2017, 20:28

Re: Simulando La Programación Con Hilos O "Programas Preñados"
-----------------------------------
Quizá este hilo debería haber ido al foro de Aplicaciones/fragmentos de código... si es así, lo siento, que el boss lo cambie si tiene a bien...
 :)  :)


-----------------------------------
v3ctor
Martes, 23 May 2017, 22:04

Re: Simulando La Programación Con Hilos O "Programas Preñados"
-----------------------------------
interesante lo bajo y después comento, es que ahora no me quedan neuronas, fea sensación.


-----------------------------------
vicr
Miercoles, 24 May 2017, 00:02

Re: Simulando La Programación Con Hilos O "Programas Preñados"
-----------------------------------
¡¡Me ha encantado Shordi!!

Hace unos años en la Universidad estuve evangelizando Linux/Gambas... a veces fue Linux Mint y en otras Fedora (y algo de Puppy Linux y Slitaz)... pues en una ocasión uno de mis compañeros me preguntó por lo del multihilo y no supe responder bien... dije que quizá con Timer, que quizá en vez de hacer UN programa habría que hacer VARIOS comunicados con el estilo Cliente/Servidor.

Esto hubiese sido bueno saberlo en esa época. (Aunque igual no me resultaba mucho lo de la adopción de Linux  :cry: )

Le echaré una miradita mañana al proyecto...

Saludos.


-----------------------------------
jguardon
Domingo, 28 May 2017, 13:04

Re: Simulando La Programación Con Hilos O "Programas Preñados"
-----------------------------------
Hola, ya he movido el hilo a este subforo.

Volviendo al tema, ¿por qué tanta complicación si gambas ya tiene la clase [url=http://gambaswiki.org/wiki/comp/gb/task]Task  (tarea) que permite ejecutar tareas en paralelo al programa principal sin bloquearlo?

Saludos


-----------------------------------
shordi
Domingo, 28 May 2017, 13:10

Re: Simulando La Programación Con Hilos O "Programas Preñados"
-----------------------------------
[quote user="jguardon" post="38371"]Hola, ya he movido el hilo a este subforo.

Volviendo al tema, ¿por qué tanta complicación si gambas ya tiene la clase [url=http://gambaswiki.org/wiki/comp/gb/task]Task  (tarea) que permite ejecutar tareas en paralelo al programa principal sin bloquearlo?

Saludos[/quote]
Por desconocimiento absoluto de dicha clase por parte del torpe preñador de ejecutables, claro. :oops:  :oops: 
 :mryellow:  :mryellow:


-----------------------------------
tercoIDE
Lunes, 29 May 2017, 11:13

Re: Simulando La Programación Con Hilos O "Programas Preñados"
-----------------------------------
[quote user="shordi" post="38372"][quote user="jguardon" post="38371"]Hola, ya he movido el hilo a este subforo.

Volviendo al tema, ¿por qué tanta complicación si gambas ya tiene la clase [url=http://gambaswiki.org/wiki/comp/gb/task]Task  (tarea) que permite ejecutar tareas en paralelo al programa principal sin bloquearlo?

Saludos[/quote]
Por desconocimiento absoluto de dicha clase por parte del torpe preñador de ejecutables, claro. :oops:  :oops: 
 :mryellow:  :mryellow:[/quote]

no te preocupes, que nadie te quita lo bailado


