|
AxIThread v3.00, Copyright © El Zooilógico, 2.000
Descripción
AxIThread permite gestionar hasta veinticinco procesos trabajando en segundo plano mientras su aplicación se dedica a otra tarea. Cada proceso se ejecutará en un hilo independiente bajo la supervisión de AxIThread, siendo su programa el encargado de administrar su funcionalidad.
Para ello la librería expone siete métodos que le otorgarán control sobre todas las acciones posibles (creación, eliminación, cambio de prioridad, etc) y dos eventos externos donde escribir el código a procesar y recuperar errores.
AxIThread puede ejecutar cualquier sección de código de su programa en un hilo independiente; basta con que indique la función que desea asignar como punto de entrada. Cada hilo puede tener dos puntos de entrada diferentes que, además, podrá modificar en cualquier momento.
Entre los distintos parámetros podrá establecer recursividad, y la función por defecto será llamada indefinidamente; asignar un intervalo, con lo que, periódicamente, se realizará una llamada al método predeterminado; habilitar protección al ejecutar código externo, con lo que se bloquearán nuevas llamadas mientras alguna esté en proceso, o deshabilitarla. Y en todo momento podrá solicitar otra tarea, que será ejecutada con preferencia sobre las demás.
Podrá crear los hilos con cualquier prioridad (dentro de los niveles permitidos) o cambiar ésta asignando un nivel inferior a tareas menos relevantes y prioridad superior a las más críticas.
Breves notas sobre aspectos a destacar
Usar AxIThread
Para hacer uso de este componente, deberá agregar la biblioteca de tipos de AxIThread a su proyecto, bien mediante la opción Componentes, bien por medio de la opción Referencias, ambas en el menú Proyecto (en VB). En ambos casos, seleccione la referencia 'AxIThread 3.0 type library'.
En el primer caso, aparecerá un nuevo icono en su paleta de componentes. Para disponer de una instancia válida deberá agregar el mismo a algún formulario de su proyecto. En el segundo caso, deberá crear una instancia al objeto 'Thread' de la librería,
Public miThreadObjeto as new Thread (o bien) Public WithEvents miThreadObjeto as Thread ... ... Set miThreadObjeto = new Thread
NOTA: La segunda declaración habilita la recepción de eventos; la primera no.
Hilos recursivos/no recursivos
Un hilo no recursivo es pasivo, esto es, permanece inactivo a la espera de mensajes que procesar. Cuando recibe un mensaje, realiza un ciclo completo para procesar el mismo y queda a la espera de nuevos mensajes.
Un hilo recursivo, por el contrario, es un hilo activo; procesa mensajes del mismo modo que un hilo no recursivo, pero en ausencia de ellos no permanece a la espera, sino que invoca constantemente el método predeterminado.
Suponga una función que compruebe la presencia de datos en un puerto de comunicaciones durante un intervalo concreto. Una vez finalizado el intervalo (o ante la recepción de datos), la función comunica la presencia o no de datos y devuelve los mismos o no.
Este es el tipo de función adecuada para ser invocada desde un hilo recursivo. Éste invoca al método, y en función del resultado, comunica al proceso padre la presencia o no de datos. Así, indefinidamente, mientras no reciba un mensaje solicitando otra tarea. El proceso padre, queda liberado de realizar una comprobación periódica del puerto, debiendo atender únicamente las notificaciones que reciba desde el hilo secundario.
Los hilos recursivos, procesarán siempre primero los mensajes recibidos; sólo en ausencia de mensajes invocarán el método por defecto. De este modo, los requerimientos del proceso padre serán atendidos de manera preferente.
Los hilos no-recursivos, realizan un muy eficiente tiempo de espera, por lo cual consumen un casi nulo tiempo de procesador. Así, son indicados para tareas no periódicas, como podría ser leer los datos del puerto de comunicaciones del ejemplo anterior, cuya presencia conocemos gracias a la notificación del hilo recursivo.
Temporizadores
Puede establecer un determinado intervalo a la hora de crear un hilo, así, éste realizará una llamada periódica a un método, que no tiene por qué ser el predeterminado. En este caso se le asignará un temporizador que, de manera regular, según el intervalo establecido, indicará al hilo que ejecute la tarea solicitada.
Este comportamiento es independiente del modo de inicio del hilo (recursivo-no recursivo), siendo posible, además, establecer tareas distintas para uno u otro caso; el hilo, dependiendo del mensaje recibido, ejecutará una tarea u otra.
El temporizador puede habilitarse en el momento de crear el hilo o con posterioridad, y puede deshabilitarlo, modificar el intervalo, o la tarea a realizar en cualquier momento.
He de destacar que, en hilos recursivos, los mensajes del temporizador, o los directos, serán atendidos con preferencia al método predeterminado.
Ejecutar código en segundo plano; el punto de entrada
En un archivo ejecutable, no hay descripciones de variables y funciones. Toda referencia a cualquiera de ellas ha sido convertida al a una posición de memoria relativa (desplazamiento) al punto de entrada del mismo. Cuando un programa se carga en memoria, lo hace en un punto concreto de la misma, y toda referencia a un dato apunta a la posición de memoria donde se almacena el mismo. Esta posición es el desplazamiento respecto a la posición origen del programa.
Cada vez que se crea un hilo, hay que asignarle su punto de entrada, esto es, la posición de memoria donde empezará a ejecutar código.
AxIThread, expone un evento (ThreadFunc) donde podrá escribir el código que desee ejecutar en segundo plano. En VB, por ejemplo, aparecerá como
Private Function Thread1_ThreadFunc(ByVal nThreadID As Long) As Long (donde nThreadID será la ID del hilo que hace la llamada)
Este será por defecto el punto de entrada de cada nuevo hilo que cree, pero podrá asignar un punto de entrada diferente al crear el hilo. La funcion que será el nuevo punto de entrada del hilo ha de seguir la descripción del evento, es decir, aceptará un párametro por valor (que será un entero largo), y devolverá un entero largo, p.e,
Private Function miThreadFunc(ByVal nThreadID As Long) As Long Dim ValorDeRetorno as Long ... ... miThreadFunc = ValorDeRetorno End Function
Para establecer el nuevo punto de entrada, basta con que indique la posición de memoria de la función al llamar al método CreateThread.
En VB, podrá hacerlo mediante el operador AddressOf(...) que devuelve la dirección de memoria del dato solicitado. Ahora bien, el uso del operador AddressOf, supone las siguientes restricciones
1- Sólo puede usarlo en un módulo (fichero .bas) 2- no podrá usarlo directamente, sólo puede invocarlo como argumento al llamar una función, por lo que necesitará una función que empaquete la dirección. 3- El dato argumento de AddressOf deberá estar en el mismo módulo, donde utilice el operador.
Por ejemplo,
Private Function EmpaquetarDireccion(FuncAdd As Long) As Long EmpaquetarDireccion = FuncAdd End Function
Public Function ObtenerPuntoEntrada(cual as integer) as long Select case cual Case 1 ObtenerPuntoEntrada = EmpaquetarDireccion AddressOf(ThreadFuncA) Case 2 ObtenerPuntoEntrada = EmpaquetarDireccion AddressOf(ThreadFuncB) ... ... Case else ObtenerPuntoEntrada = 0 End select End Sub
Public Function ThreadFuncA(ByVal nThreadID As Long) As Long
'codigo a ejecutar
ThreadFuncA = 0 End Function
Public Function ThreadFuncB(ByVal nThreadID As Long) As Long
'codigo a ejecutar
ThreadFuncB = 0 End Function
El código anterior debe estar en el mismo modulo 'bas' donde utilice AddressOf, pero eso no le impide llamar desde las funciones a cualquier otra sección del programa
Public Function ThreadFuncX(ByVal nThreadID As Long) As Long Dim longVar as Long longVar = FormW.FuncionV(ByVal nThreadID) ThreadFuncX = ModuloY.FuncionZ(ByVal nThreadId, longVar, ...) End Function
Si ha establecido un temporizador puede asignarle al mismo un punto de entrada independiente, con lo que el hilo ejecutará una acción diferente cuando reciba un requerimiento del mismo.
Sin menoscabo de lo anterior, en cualquier momento podrá modificar los puntos de entrada predeterminados. Asímismo, ocasionalmente, podrá enviar un mensaje solicitando otra tarea (otra función) que será ejecutada de inmediato y una única vez volviendo después al comportamiento predeterminado. Así, cada hilo, puede tener asignadas hasta tres tareas distintas en un momento dado.
Todo ello le otorga una gran flexibilidad a la hora de ejecutar código en segundo plano.
Así,miObjetoThread.CreateThread (No se indica punto de entrada, se usará el predeterminado, evento suObjeto_ThreadFunc(...))
miObjetoThread.CreateThread(1,,-1, ObtenerPuntoEntrada(2)) miObjetoThread.CreateThread(1,,-1, AddressOf(ThreadFuncB)) (sólo en en mismo módulo) (el punto de entrada sera ThreadFuncB)
Evidentemente, el valor indicado como punto de entrada puede contener una dirección incorrecta. En ese caso, si el hilo es recursivo y la dirección errónea es el punto de entrada predeterminado, su estado cambiará a no recursivo; si es programado (temporizado), se desabilitará el temporizador. En ambos casos recibirá, un código de error en el evento ThreadDone. También, recibirá un código de error, si la dirección errónea fue indicada como parámetro de un mensaje directo.
Estos valores pueden ser:
-. 2147483632 (hex 0x7FFFFFF0), no recursivo (función por defecto) -. 2147483634 (hex 0x7FFFFFF2), no recursivo (parámetro de mensaje) -. 2147483635 (hex 0x7FFFFFF3), programado no recursivo -. 2147483636 (hex 0x7FFFFFF4), recursivo (función por defecto) -. 2147483638 (hex 0x7FFFFFF6), recursivo (parámetro de mensaje) -. 2147483639 (hex 0x7FFFFFF7), programado y recursivo
En los casos 3 y 6, se habrá eliminado el temporizador. En los casos 4 y 5, el estado del hilo habrá cambiado a no recursivo.
Este evento, que verá como,
Private Function Thread1_ThreadDone(ByVal nThreadID As Long, ByVal retval as long) (nThreadID, hilo que hace la llamada; retval, valor de retorno o código de error)
además de la presencia de errores, comunicará el código de retorno de un hilo que esta siendo eliminado. De este modo, podrá realizar las tareas de limpieza que sean necesarias.
Modo protegido
La ejecución de código externo pueden estar (o no) protegida: en el primer caso, las invocaciones a función se realizarán una a una, impidiendo nuevas llamadas mientras una esté en proceso. Si las llamadas acceden a datos sensibles a ser manipulados por varios procesos al mismo tiempo (una variable global, por ejemplo), deberá habilitar la protección para evitar la corrupción de los mismos (vea apéndice A). Si la protección está deshabilitada, las notificaciones se realizarán independientemente del número de llamadas en proceso. Si estas llamadas operan con valores no sensibles como variables locales, valores de retorno, arrays indexados o incluso variables globales (siempre y cuando sean de sólo-lectura), puede deshabilitar la protección. En el primer caso, obtiene más seguridad; en el segundo mayor rendimiento. La elección de un modelo u otro dependerá de la implementación del código de su programa. Si cada hilo tiene un punto de entrada diferente, o no opera con datos sensibles a ser manipulados por múltiples procesos al mismo tiempo, no será necesario que habilite protección y la ejecución del código será más eficiente.
La protección es un parámetro independiente para cada hilo; así, si múltiples hilos hacen uso de la misma sección de código, y ésta es sensible a la manipulación simultánea de datos, deberá habilitar protección para cada uno de ellos. La exclusión simultánea sólo es válida para hilos protegidos entre sí, y sólo se garantiza entre ellos, los protegidos nada saben de los desprotegidos y éstos, a su vez, nada saben de los primeros.
Suponga tres hilos que accedan a una función en cuyo cuerpo se incremente un contador para luego, según el valor del mismo, realizar una operación u otra. Si ha habilitado protección en dos de ellos, pero no en el tercero, los dos primeros no podrán acceder simultáneamente a la sección de código, pero sí el tercero, independientemente del estado de los primeros y, del mismo modo, si aquel para el que no ha habilitado protección está ejecutando la función, cualquiera de los primeros, podrá acceder a la misma, (vea apéndice A).
El paso de argumentos
Los métodos expuestos por AxIThread requieren parámetros obligatorios, y/o opcionales. Entre los opcionales, cabe diferenciar aquellos que toman valores por defecto, y aquellos que no lo hacen. En todo caso, todo parámetro opcional puede obviarlo, pues en su ausencia tomará su valor por defecto o será descartado. Así, son válidas las llamadas siguientes:
nThrID = miThreadOb.CreateThread nThrID = miThreadOb.CreateThread(1,,500,,1,,,nResult) nThrID = miThreadOb.CreateThread(, 1, , , ,25000)
Puede prescindir de aquellos parámetros opcionales que no seán de interés, pero los indicados deben ir en la posición que les corresponde.
Métodos
En la descripción del formato de los métodos expuestos por AxIThread, los parámetros entre corchetes indican parámetros opcionales. Si, además, aparece un valor, este será el valor que tomará por defecto en caso de no ser indicado.
PauseThread
Suspende la ejecución del hilo indicado hasta que sea resumido o eliminado.
Este método no retorna ningún valor.
Formatos (C & VB)
void PauseThread (long nThreadID)
PauseThread (nThreadID as long)
nThreadID, ID del hilo a suspender.
ResumeThread
Resume un hilo previamente suspendido.
No retorna ningún valor.
Formatos (C & VB)
void ResumeThread (long nThreadID)
ResumeThread (nThreadID as long)
nThreadID, ID del hilo a resumir.
ThreadPriority
Establece la prioridad del hilo al valor indicado en nLevel.
No retorna ningún valor.
Formatos (C & VB)
void ThreadPriority (long nThreadID, [long nLevel = 0])
ThreadPriority (nThreadID as long, [nLevel as long = 0])
nThreadID, ID del hilo.
nLevel, nuevo nivel de prioridad. Los valores admitidos son de 0 (mínima) a 4 (máxima), siendo 2 el valor por defecto del sistema (8).
CreateThread
Crea un nuevo hilo de ejecución, de acuerdo a los argumentos especificados; siempre ejecutará un ciclo completo nada más ser creado.
Si no hay error, o éste no ha impedido la creación del hilo, CreateThread devuelve un entero largo que será la ID asignada al hilo que lo identifica. Deberá indicar esta ID cuando llame a las demás funciones. En caso contrario retornará 0, y colocará un código de error en nResult.
Formatos (C & VB) long CreateThread([BOOL bProtected = true], [short nPriority = 2],[long nRetCode = 0], [long FuncAdd = 0], [BOOL bRecursive = false], [long nAutoCallInterval = 0], [long AutoFuncAdd = 0], [long *nResult]
CreateThread([bProtected As Boolean = true], [nPriority As Integer= 2], [nRetCode As long = 0], [FuncAdd As long = 0], [bRecursive As Boolean= false], [nAutoCallInterval As long = 0], [AutoFuncAdd As long = 0], [nResult As long]
bProtected, habilitar protección (verdadero), no habilitar (falso). Por defecto, estará habilitada, (vea nota).
nPriority, nivel de prioridad predeterminado. Los valores admitidos son de 0 (mínima) a 4 (máxima). Por defecto 2 (prioridad normal).
nRetCode, código de retorno de un hilo (valor que forzará la salida del mismo), (vea al pie).
FuncAdd, dirección de memoria que será el punto de entrada del hilo, (vea nota).
bRecursive, si indica (verdadero) el hilo será iniciado como recursivo, (vea nota).
AutoCallInterval, intervalo a asignar al temporizador, (vea nota).
AutoFuncAdd, punto de entrada para el temporizador.
nResult, resultado de la operación.
Códigos de error devueltos
0, ningún error. 1, se ha creado el hilo pero no ha sido posible crear el temporizador. 15, (hex. F), no se ha creado el hilo (bien hay 25 hilos ejecutándose, bien ha sido imposible).
Los hilos permanecen activos hasta que se descargue el componente, se les indique terminar mediante ThreadStop, o porque tengan establecido un código de retorno. Si establece un código de retorno específico para un hilo, y la función que es llamada por el mismo devuelve ese valor, el hilo terminará y será eliminado. Este valor es, por defecto, nulo (0). Si la función llamada no devuelve nada (a efectos prácticos eso es lo mismo que 0), el hilo recibirá el valor de retorno asignado y terminará inmediatamente. Ténga en cuenta que, dado que cada hilo puede tener asignadas hasta tres tareas diferentes en un momento dado, pero un único valor de retorno; cualquiera de ellas puede forzar la eliminación del hilo.
StopThread
Detiene la ejecución del hilo indicado en nThreadID.
Devolverá 0 si no ha habido error ó 15 (hex 0xF) si no existe el hilo indicado en nThreadID.
Formatos (C & VB) long StopThread(long nThreadID, [BOOL bIgnoreMsgQueue = false])
StopThread(nThreadID As long , [bIgnoreMsgQueue As Boolean = false]) As long
nThreadID, ID del hilo a detener. Esta ID es la que devuelve CreateThread y que identifica a cada hilo.
bIgnoreMsgQueue, ignorar mensajes pendientes. Si está configurado como falso, se procesarán los mensajes pendientes antes de eliminar el hilo. Si está configurado como verdadero, se eliminará el hilo inmediatamente, ignorando los mismos.
LoopThread
Coloca un nuevo mensaje en la cola de mensajes del hilo referido como nThreadID, indicando opcionalmente la operación a realizar.
Devolverá 0 si no ha habido error ó 15 (hex 0xF) si no existe el hilo indicado en nThreadID.
Formatos (C & VB) long LoopThread(long nThreadID, [long FuncAdd = 0])
LoopThread(nThreadID As long, [FuncAdd As long = 0]) As long
nThreadID, ID del hilo al que comunicar mensajes.
FuncAdd, dirección de memoria donde realizar un ciclo completo.
Los hilos recursivos llaman indefinidamente el método predeterminado; los programados (temporizados) cada vez que vence el intervalo establecido; los recursivos y programados en ambos casos. Sin embargo, los hilos no recursivos ni programados, llaman a su punto de entrada predeterminado una sola vez nada más ser creados, y luego quedan a la espera de realizar un nuevo ciclo.
Así, esta función cubre dos propósitos:
En primer lugar, para indicar a un hilo recursivo y/o programado que realice otra tarea, llame esta función con la dirección de una función de su programa. Así, este hilo puede llegar a realizar hasta tres tareas diferentes en un momento dado.
En segundo lugar, para indicar a un hilo inactivo (no recursivo ni programado), que ejecute un nuevo ciclo (bien del método predeterminado, bien de la función indicada).
ModifyThread
Permite alternar entre modo recursivo/no recursivo; establecer, modificar o eliminar un temporizador; cambiar el punto de entrada predeterminado y el punto de entrada del temporizador.
Devolverá 0 si no ha habido error, 1 si no es posible habilitar un temporizador ó 15 (hex 0xF) si no existe el hilo indicado en nThreadID.
Formatos (C & VB) long ModifyThread(long nThreadID, [BOOL bToggleState = 0], [long FuncAdd = 0],[long nNewInterval = 0], [long AutoFuncAdd = 0])ModifyThread(nThreadID As long, [bToggleState As Boolean= 0],[FuncAdd As long = 0], [nNewInterval As long= 0], [AutoFuncAdd As long = 0])
nThreadID, ID del hilo a modificar.
bToggleState, alternar modo recursivo/no recursivo.
FuncAdd, nuevo punto de entrada predeterminado, (vea nota - vea al pie).
nNewInterval, nuevo intervalo del temporizador, (vea nota).
AutoFuncAdd, nuevo punto de entrada para el temporizador, (vea al pie).
Los valores indicados tanto en FuncAdd como en AutoFuncAddserán interpretados de la siguiente manera:
- (-1), no se realizarán cambios. - (0), deshabilitar punto de entrada, ahora se llamará al evento por defecto ThreadFunc. - cualquier otro valor será asignado como nuevo punto de entrada.
Si el valor indicado como punto de entrada en algún parámetro es erróneo recibirá un evento, indicando la causa y la acción realizada, (vea nota).
Apéndices
Sobre el modo protegido
Si varios hilos acceden de manera simultánea a una función y no desea habilitar protección, no utilice variables globales en el cuerpo de las funciones de notificación, a menos que sean de solo lectura. Observe el siguiente fragmento de código:
Private Function FuncionPuntodeEntrada(ByVal nThreadID As Long) as longGlobalData = GlobalData + 1 If GlobalData = 5 Then... FuncionPuntodeEntrada = ValorDeRetorno ...End IfEnd Function
Cada vez que la función es llamada se incrementa el valor de la variable GlobalData; si su valor es 5, se realizan una serie de operaciones y se devuelve el valor de retorno asignado al hilo. Si un hilo llama a la función cuando la variable contiene el valor 3, incrementa esta variable y antes de chequear el contenido, el sistema pasa el control a otro hilo que a su vez modifica la misma, cuando el control retorne al primer hilo, el contenido de la variable no será el esperado 4 sino 5 (y se ejecutará el bloque if).
Este es el tipo de situación que debe tratar de evitar, bien empleando variables locales, con lo cual cada hilo trabajará con una copia distinta, bien usando arrays,
Private Function FuncionPuntodeEntrada(...)GlobalData(nThreadID) = GlobalData(nThreadID) + 1 If GlobalData(nThreadID) = 5 Then... FuncionPuntodeEntrada = ValorDeRetorno(nThreadID) ...End IfEnd Function
Si le es absolutamente indispensable chequear una variable global, asegúrese que es de solo lectura o implemente algún tipo de sincronización. El caso más sencillo sería:
Private Function FuncionPuntodeEntrada(...)Static Lock as Boolean
Do while LockSleep(1) 'pasemos el control a otro hiloLoop
Lock = true GlobalData = GlobalData + 1 If GlobalData = 5 Then... FuncionPuntodeEntrada = ValorDeRetorno ...End If Lock = falseEnd Function
Si aún así, experimenta problemas, deberá habilitar protección.
Registrarse
No voy a repetirle lo que es shareware, si lo desea puede leer la nota al final del texto. Pero si algunos apuntes de mi manera de ver las cosas.
En primer lugar, al diseñar esta librería he pensado en facilitar el uso de características interesantes de los ‘modernos’ sistemas operativos, que de otro modo sólo son accesibles por medio de continuas llamadas al API de Windooze. Considero que lo encontrará práctico y fácil de usar.
Me ha llevado un tiempo y me he tomado un trabajo hasta que he quedado satisfecho del funcionamiento de un componente del que espero sirva de ayuda en sus desarrollos.
Por otro lado, trato de ganarme la vida con esto, con lo cual debo buscar una manera de compersar el trabajo que me tomo, y las horas de ‘autismo’ que soportan quienes viven conmigo.
No soy partidario de facilitar componentes con características mermadas o limitadas en el tiempo, así que AxIThread es totalmente funcional. Pero considero que quienes se registran deben disfrutar de alguna ventaja, por pequeña que esta sea, frente a quienes no lo hacen. En este caso, la única ventaja de registrarse (aparte de contribuir a mantener la filosofía shareware) será eliminar la ventana que aparece cuando la librería se carga en memoria.
Para registrarse notifíquelo en la direccion kikusi@arrakis.es, indicando los siguientes datos de registro:
Nombre (ya sea particular o comercial). Dirección de correo (eMail). Número de licencias (solo licencias empresariales).
No olvide indicar la librería que desea registrar (AxIThread).
La forma de pago será (preferiblemente) por transferencia bancaria a la cuenta:
2038-4028-57-6000036475
o bien por giro postal o cheque pagaderos a:
Miguel Perancho Hevia San Bartolomeo da Freixa 32514 - Boborás, Ourense España
indicando en cualquier caso como concepto el nombre usado para registrarse. Una vez hecho efectivo, recibirá el número de licencia para registrar el componente en la dirección solicitada.
Lista de precios: (Ene-Dic 2.000)
AxIThread, desarrolladores particulares,
Licencia monopuesto, 11.500 pts, 70 euro, $70 US
AxIThread, empresas,
Licencia única, 70.000 pts, 425 euro, $425 US
Licencia total, a consultar
AxIThread, centros de enseñanza,
Consultar para condiciones especiales
Recuerde, AxIThread es una librería, no un programa. Es el desarrollador quien satisface la cuota de registro, no el usuario final. Una vez registrado, el desarrollador obtiene una licencia MONOPUESTO completa. Puede utilizarla en sus proyectos y distribuírla con ellos sin cargo alguno. Obviamente, un desarrollador/un puesto, una licencia.
Más información - Descargas.
Acerca del shareware
Hasta hace bien poco, los programas comerciales se compraban prácticamente a ciegas, siendo después de la compra cuando evaluábamos el producto; a no ser que, ante la perspectiva de un volumen grande de ventas, la empresa responsable del desarrollo o comercialización de la misma, se aviniese a hacernos una demostración. Hoy en día es más habitual que, de manera anterior al lanzamiento de la versión final de un programa, pase por nuestras manos una 'pre-Release', 'Demo' o 'Beta' del mismo con características recortadas o limitada en el tiempo con el fin de evaluar su funcionamiento y/o rendimiento. El auge del shareware tiene bastante que ver con esto.
Ya ha pasado el tiempo en que el shareware y el freeware era software de menor calidad que los programas comerciales; como muestra puede probar cualquiera de los programas share de diseño o retoque que seguramente pueda instalar desde el cd-rom que le regala su revista favorita.
Como bien sabe la filosofía sobre la que se apoya el shareware es la de ‘probar antes de comprar’. Así, frente al programa comercial, un usuario comprueba las excelencias o carencias del software antes de tomar una decisión sobre la adquisición del mismo. Y en este caso, el desembolso exigido es menor. También es cierto (aunque no siempre) que un programador, o pequeño grupo de programadores, no puede competir frente a un equipo formado por numerosas personas y presupuestos millonarios a la hora de diseñar proyectos complejos. En cambio, sí puede ofrecer otro tipo de soluciones (ya sean componentes, add-ins o programas completos) de utilidad para el resto de usuarios.
Las personas que pasamos largos ratos delante de la dichosa maquinita, en ocasiones nos topamos con que al fabuloso programa ,que ocupa 200 ricos megas de nuestro disco duro y que tanto y tan bien hace, le falta algun detalle que nos facilitaría el trabajo en gran medida, detalle al que algún programador, en alguna parte del mundo, le ha encontrado solución y nos la ofrece a cambio de una compensación a su dedicación, generalmente poco onerosa.
El shareware se basa en la confianza que deposita el programador de una pequeña utilidad que nos ahorra algún esfuerzo en que nosotros compensemos el suyo. No es raro encontrar aquellos que sólo piden que les enviemos una tarjeta informando de quienes somos, dónde nos encontramos y que nos parece su trabajo, aunque es más habitual, y yo en este caso así lo he decidido, que la compensación sea económica.
Esto es shareware. Yo ofrezco algo que cualquiera puede tomar y probar cuanto guste. Si ese alguien, después de probarlo, decide usarlo en la práctica, es libre de hacerlo siempre y cuando cumpla las condiciones en que se lo ofrezco.
Todo esto no sirve de nada sin el apoyo de los usuarios. Si nadie se registrase, el programador dejaría de desarrollar para el usuario en general, y quedaríamos en manos de los de siempre. Las ventajas de apoyar el shareware son obvias: disponer de una ingente cantidad de software frente al (generalmente más caro, aunque generalmente también más completo) software 'comercial'.
Pero al menos tendrá la oportunidad de elegir entre muchas posibilidades y no verse forzado a escoger entre unos pocos.
Ahora, usted es quien decide...
El autor (o culpable)
Más información - Descargas.
AxIThread v3.00, Copyright © El Zooilógico, 2.000
| |