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.
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
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
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...
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)
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:
y este código:
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
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
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
ProgramaPreñado.zip | ||
Descripción: | Descargar |
|
Nombre del archivo: | ProgramaPreñado.zip | |
Tamaño: | 24.04 KB | |
Descargado: | 39 veces |
ProgramaPreñado.zip | ||
Descripción: | Descargar |
|
Nombre del archivo: | ProgramaPreñado.zip | |
Tamaño: | 24.04 KB | |
Descargado: | 39 veces |
ProgramaPreñado.zip | ||
Descripción: | Descargar |
|
Nombre del archivo: | ProgramaPreñado.zip | |
Tamaño: | 24.04 KB | |
Descargado: | 39 veces |