Microsoft Visual Basic versión 5.0 Service Pack 2,
Notas de la versión


© 1996-1997 Microsoft Corporation

Visual Basic versión 5.0 Service Pack 2 es una actualización a las ediciones Profesional, Empresarial y Control Creation de Visual Basic. La versión Control Creation (disponible en inglés) tiene una actualización independiente. Permite la separación de subprocesos para proyectos de Visual Basic que contienen elementos de la interfaz de usuario, como formularios y controles, y depura varios errores conocidos de Visual Basic 5.0. (Busque VB5FixListSP en el sitio Web Knowledge Base en http://www.microsoft.com/kb/default.asp.)

Aplicar el Service Pack 2 a su copia con licencia de Visual Basic le permite crear controles ActiveX(TM) y documentos ActiveX que funcionan bien en clientes de subprocesos múltiples como Internet Explorer 4.0. Si tiene la edición Profesional o Empresarial de Visual Basic, también puede crear lo siguiente:

  • Archivos DLL con separación de subprocesos que muestran formularios.
  • Componentes de subprocesos múltiples que emplean diseñadores ActiveX, como el diseñador UserConnection.
  • Aplicaciones cliente de subprocesos múltiples para probar estos componentes.

Esta mejora del modelo de separación de subprocesos es la única característica de Visual Basic versión 5.0 Service Pack 2.

Estas notas de la versión contienen información complementaria a la documentación de Microsoft® Visual Basic® 5.0 incluida en la Ayuda y en los Libros en pantalla. Si desea información adicional, visite el sitio Web de Microsoft Visual Basic en http://www.microsoft.com/vbasic/.

Contenido

Introducción a los cambios en el modelo de separación de subprocesos

Seleccionar un modelo de subprocesos múltiples para su proyecto
Limitaciones de la característica de Modelo de separación de subprocesos
Convertir proyectos ya existentes

Cambios a la documentación de Visual Basic 5.0

Cambios a "Modelo de separación de subprocesos en Visual Basic"
Cambios a "Diseñar DLL seguras para los subprocesos"
Cambios a "Diseñar componentes de subprocesos múltiples fuera de proceso"

Escenarios de usuario

Controles con separación de subprocesos para Internet Explorer 4.0
Crear una DLL segura para los subprocesos con formularios
Crear una aplicación de subprocesos múltiples de prueba

Nota sobre las secuencias de comandos seguras para controles ActiveX

Lista de componentes

 

Introducción a los cambios en el modelo de separación de subprocesos

Los proyectos creados con Visual Basic versión 5.0 Service Pack 2 pueden aprovechar el modelo de separación de subprocesos sin necesidad de suprimir elementos visuales como formularios y controles. La aplicación de Service Pack 2 hace que los formularios, controles de usuario, documentos de usuario y diseñadores ActiveX sean seguros de cara a los subprocesos. Service Pack 2 incluye lo siguiente:

  • Versiones con separación de subprocesos de todos los controles ActiveX que se proporcionan con Visual Basic 5.0, excepto DBGrid, MSChart y otros controles heredados que se incluían en el directorio Tools por compatibilidad con versiones anteriores.
  • Una versión con separación de subprocesos del diseñador ActiveX UserConnection.
  • Una nueva opción de Modelo de subprocesos que le permite volver a compilar los proyectos de controles ActiveX y documentos ActiveX como archivos .ocx y .dll con separación de subprocesos.

Nota   el código auxiliar para los diseñadores ActiveX es ahora un código de separación de subprocesos seguro para los subprocesos, pero esto no garantiza que un determinado diseñador sea seguro. Si está usando un diseñador de otros proveedores, debe consultar a su proveedor.

Limitaciones de la edición Control Creation, versión 5.0

Las únicas partes de este documento que se aplican a la edición Control Creation son aquellas que afectan a los proyectos de controles ActiveX seguros para los subprocesos.

Si usa la edición Control Creation para crear controles ActiveX con separación de subprocesos, debe usar un cliente de subprocesos múltiples como Internet Explorer 4.0 para probar el comportamiento de subprocesos múltiples de sus controles. No puede usar la edición Control Creation para crear un cliente de prueba de subprocesos múltiples.

 

Seleccionar un modelo de subprocesos múltiples para su proyecto

Service Pack 2 cambia las opciones de la ficha General del cuadro de diálogo Propiedades del proyecto. Tras aplicar Service Pack 2, la opción Ejecución desatendida deja de estar activada en el modelo de subprocesos de su proyecto. Puede seleccionar un valor para la opción Modelo de subprocesos sin marcar su proyecto como de Ejecución desatendida.

Para configurar el modelo de subprocesos para un proyecto DLL ActiveX, Exe ActiveX o control ActiveX

  1. En el menú Proyecto, haga clic en Propiedades del <proyecto> para abrir el cuadro de diálogo Propiedades del proyecto.
  2. En la ficha General, seleccione las opciones que desee en el cuadro Modelo de subprocesos.
  • Para los proyectos de DLL ActiveX y control ActiveX, puede elegir entre Subprocesos separados o Subprocesos sencillos.
  • Para los proyectos Exe ActiveX, puede especificar que cada nuevo objeto se cree en un nuevo subproceso (Subproceso por objeto) o puede limitar su componente a un conjunto fijo de subprocesos. Un tamaño de conjunto de subprocesos igual a uno (1) hace que el proyecto sea de un único proceso, mientras que un conjunto mayor hace que el proyecto tenga separación de subprocesos.

Nota   Cuando cambie el modelo de subprocesos de un proyecto ya existente, ocurrirá un error si el proyecto utiliza controles ActiveX de un único subproceso. Visual Basic impide utilizar controles de un único subproceso en proyectos con separación de procesos, tal y como se describe en Convertir proyectos ya existentes.

Nota   Cuando especifica Subproceso por objeto (o un conjunto de subprocesos mayor que uno) para un proyecto Exe ActiveX, sólo los objetos creados externamente se crean en nuevos subprocesos. (Consulte "Diseñar componentes de subprocesos múltiples fuera de proceso" en los Libros en pantalla.) Las opciones Subproceso por objeto y Conjunto de subprocesos no están disponibles para proyectos de DLL ActiveX y controles ActiveX, ya que la creación de procesos está controlada por la aplicación cliente.

Importante   Para los usuarios de las ediciones Profesional y Empresarial, las consecuencias de seleccionar Subproceso por objeto o Conjunto de subprocesos se explican en detalle en "Diseñar componentes de subprocesos múltiples fuera de proceso" en los Libros en pantalla.

Service Pack 2 y Ejecución desatendida

Service Pack 2 no cambia el funcionamiento de la opción Ejecución desatendida. Dicha opción sigue permitiendo crear componentes que se pueden ejecutar sin la intervención del operador en servidores de red. El único cambio realizado por Service Pack 2 es que la selección de Ejecución desatendida no afecta al modelo de subprocesos de su componente.

 

Limitaciones de la característica de Modelo de separación de subprocesos

Las siguientes limitaciones se aplican a todas las ediciones de Visual Basic.

  • El entorno de desarrollo no permite la depuración de subprocesos múltiples. Si dispone de Microsoft Visual Studio puede depurar un componente con separación de subprocesos con el depurador Visual Studio tras compilarlo a código nativo con información de depuración. También necesitará una aplicación cliente de subprocesos múltiples para probar y depurar componentes en proceso(archivos .dll y .ocx).
  • Los formularios MDI primarios y secundarios deben compartir datos de formas que son difíciles de hacer seguros para los subprocesos. Por tanto, no se permiten formularios MDI en proyectos con separación de subprocesos. En el menú Proyecto, el comando Agregar MDIForm está atenuado en los proyectos de DLL ActiveX con separación de procesos y en los proyectos de Exe ActiveX para los que se ha seleccionado Subproceso por objeto (o con un conjunto de subprocesos mayor que uno). Si cambia el modelo de subprocesos a Separación de subprocesos en un proyecto que contiene formularios MDI, ocurrirá un error.
  • Los controles ActiveX de un único subproceso puede causar numerosos problemas en los clientes de subprocesos múltiples, además de tener un funcionamiento muy lento. Por tanto, Visual Basic impide el uso de controles de un único subproceso en aquellos proyectos donde se haya configurado el Modelo de subprocesos como Separación de procesos. Si desea información más detallada al respecto, vea Convertir proyectos ya existentes.
  • A las propiedades y los métodos "friend" sólo los pueden llamar objetos del mismo subproceso. Puesto que no forman parte de la interfaz pública de un objeto, no pueden ordenarse entre subprocesos.
  • Los Documentos ActiveX de proyectos Exe ActiveX no serán del modelo de separación de subprocesos seguros para los subprocesos a menos que seleccione Subproceso por objeto, o Conjunto de subprocesos con un tamaño mayor que uno.
  • Cuando un subproceso muestra un formulario con vbModal, el formulario será modal sólo para el código y para los formularios de ese subproceso. El código que se ejecute en otros subprocesos no se bloqueará y los formularios mostrados por otros subprocesos seguirán activos.
  • La técnica de Arrastrar y colocar entre formularios y controles sólo funcionará si el origen y el destino del arrastre están en el mismo subproceso. (Sin embargo, la técnica arrastrar y colocar de OLE funcionará de manera universal.)
  • DDE entre formularios sólo funcionará si los formularios están en el mismo subproceso.

 

Convertir proyectos ya existentes

Una vez que haya aplicado Visual Basic versión 5.0 Service Pack 2, podrá agregar separación de subprocesos a sus proyectos ya existentes si cambia la opción Modelo de subprocesos, tal y como se describe en Seleccionar un modelo de subprocesos múltiples para su proyecto, y vuelve a compilar el proyecto. Para muchos proyectos, esto es todo lo que necesitará hacer.

Si un proyecto ya existente de DLL ActiveX, EXE ActiveX o control ActiveX utiliza controles componentes de un único subproceso, intentar cambiar el Modelo de subprocesos a Separación de subprocesos producirá error. Debido al número y a la gravedad de los problemas que los controles ActiveX con un único subproceso causan a los clientes de múltiples subprocesos, Visual Basic no permite utilizarlos en proyectos de componentes ActiveX.

Si tiene un proyecto ya existente que emplea un control de un único subproceso, póngase en contacto con el proveedor para ver si existe una versión con separación de procesos.

Forzar el uso de controles de un único subproceso

Es posible "engañar" a Visual Basic para que utilice un control de un único subproceso en un proyecto con separación de subprocesos si modifica manualmente el archivo .vbp. No lo haga. Entre los problemas que los controles ActiveX de un único subproceso pueden causar cabe citar los siguientes:

  • Si un usuario cambia (con la tecla TAB) a un control de un único subproceso en un formulario que se está ejecutando en otro subproceso diferente, no podrá volver de nuevo al control. Esto se debe a que el subproceso del control de un único subproceso no tiene contexto para el enfoque en el subproceso del formulario. La única manera de que el usuario cambie el enfoque en esta situación es mediante el mouse. Usar un control de un único subproceso como un componente de un control con separación de subprocesos provoca problemas similares.
  • En una aplicación de subprocesos múltiples, activar un formulario haciendo clic en un control de un único subproceso fallará si el formulario está en otro subproceso diferente. Esto también ocurre al hacer clic en un componente de un único subproceso de un control con separación de subprocesos.
  • Usar un OCX de un único subproceso en una aplicación de subprocesos múltiples provoca problemas de rendimiento, puesto que todos los controles proporcionados por el OCX deben ejecutarse en el mismo subproceso. Esto significa que para los controles de formularios que se ejecutan en diferentes subprocesos, toda la comunicación requiere costosas llamadas entre subprocesos. Un control ActiveX con separación de subprocesos que utilice controles componentes de un único subproceso provocará problemas de rendimiento similares.
  • En una aplicación de subprocesos múltiples, la tecla TAB y las teclas de acceso (por ejemplo, Alt+A) no funcionarán para los controles de un único subproceso que no estén en el subproceso principal de la aplicación. Un control ActiveX con separación de subprocesos que utilice controles componentes de un único subproceso experimentará problemas similares.
  • Si su control con separación de subprocesos configura la propiedad Picture de un control componente de un único subproceso (o cualquier otra propiedad que tome un objeto Picture), se producirán errores en clientes de subprocesos múltiples. Esto se debe a que el objeto Picture no se puede ordenar entre subprocesos.

Importante   Los controles de un único subproceso pueden causar estos y otros problemas en cualquier componente o aplicación de subprocesos múltiples que genere, ya sea con Visual Basic o con cualquier otra herramienta de desarrollo.

Consideraciones de diseño para proyectos de DLL ActiveX y controles ActiveX

Los objetos proporcionados por componentes en proceso se crean en subprocesos del cliente; su DLL u OCX no puede crear subprocesos por sí mismo. La primera vez que un subproceso cliente crea una instancia de un objeto proporcionado por su componente, se creará un nuevo apartado para ese subproceso y su subrutina Sub Main se ejecutará para el nuevo apartado. Todos los objetos que proporcione su componente para ese subproceso cliente residirán en el mismo apartado.

Si ha diseñado su componente de forma que todas las instancias de una clase comparten datos globales comunes, esos datos sólo se compartirán ahora entre los objetos que estén en el mismo subproceso. Si hay código global que tiene acceso a una base de datos, ese acceso no ocurrirá de forma separada para cada subproceso.

Por ejemplo, suponga que un cliente de subprocesos múltiples muestra una instancia de su control Widget en un formulario del subproceso A y dos instancias más en un formulario en el subproceso B. Las instancias del control estarán en dos apartados, cada una con una copia de las variables globales. La subrutina Sub Main se ejecutará una vez por cada apartado. Los dos controles del subproceso B compartirán el estado global, separados del estado global del control del subproceso A.

En Cambios al "Modelo de separación de subprocesos en Visual Basic" y en Cambios a "Diseñar DLL seguras para los subprocesos" de este documento, y en los correspondientes temas de los Libros en pantalla de Visual Basic 5.0, se explican otras consideraciones de diseño.

Consideraciones de diseño para proyectos EXE ActiveX

La diferencia más importante entre los componentes de un único subproceso y los componentes con separación de subprocesos fuera de proceso es que todos los datos globales (incluyendo las propiedades del objeto App) se duplican para cada subproceso. Una de las implicaciones de esto es que la subrutina Sub Main se ejecutará cada vez que se cree un nuevo subproceso.

En Cambios a "Modelo de separación de subprocesos en Visual Basic" y en Cambios en "Diseñar componentes de subprocesos múltiples fuera de proceso" en este documento, y en los temas correspondientes de los Libros en pantalla de Visual Basic 5.0, se explican otras consideraciones de diseño para los componentes fuera de proceso.

 

Cambios a la documentación de Visual Basic 5.0

Los siguientes temas describen cambios específicos en los temas indicados de los Libros en pantalla de Visual Basic 5.0:

Cambios a "Modelo de separación de subprocesos en Visual Basic"
Cambios a "Diseñar DLL seguras para los subprocesos"
Cambios a "Diseñar componentes de subprocesos múltiples fuera de proceso"

Si tiene las ediciones Profesional o Empresarial de Visual Basic, puede encontrar estos temas en los Libros en pantalla mediante el panel Contenido:

Guía de herramientas componentes
  Crear componentes ActiveX
    Generar componentes de código
      Escalabilidad y subprocesos múltiples

Nota   El explorador de los Libros en pantalla no se incluye en la edición Control Creation. Los temas indicados anteriormente no se incluyen en las partes de la documentación de Visual Basic 5.0 que se pueden descargar para su uso con la edición Control Creation. Sin embargo, el material sobre la reentrada y el diseño de DLL seguras para los subprocesos contenido en los dos temas siguientes será de interés para los usuarios de la edición Control Creation.

 

Cambios a "Modelo de separación de subprocesos en Visual Basic"

El tema original de los Libros en pantalla explica que Visual Basic mantiene una copia distinta de los datos globales para cada subproceso. Un efecto lateral de esto, que no se menciona en los Libros en pantalla, es que la subrutina Sub Main se ejecuta para cada nuevo apartado (es decir, para cada nuevo subproceso). De lo contrario, no habría ninguna manera de inicializar datos globales para el subproceso. Esto se explica con más detalle en Cambios a "Diseñar DLL seguras para los subprocesos" y en Cambios a "Diseñar componentes de subprocesos múltiples fuera de proceso", más adelante.

Dónde puede utilizar múltiples subprocesos

Ya no es verdad que los componentes se deben marcar para Ejecución desatendida con el fin de poder usar la separación de procesos. La Ejecución desatendida es ahora una opción independiente en la ficha General del cuadro de diálogo Propiedades del proyecto, tal y como se describió anteriormente en Seleccionar un modelo de subprocesos múltiples para su proyecto.

Reentrada

El tema original indica que cuando se hace una llamada entre subprocesos, el método al que está llamando se protege frente a la reentrada siempre y cuando el método no ceda (por ejemplo, llamando a DoEvents). Es importante hacer notar que un método también cede si se hace una llamada propia entre subprocesos o entre procesos, o si se muestra un formulario.

 

Cambios a "Diseñar DLL seguras para los subprocesos"

El tema de los Libros en pantalla se aplica ahora a los proyectos de control ActiveX, así como a los proyectos de DLL ActiveX.

El procedimiento para que un proyecto de DLL ActiveX tenga separación de procesos ha cambiado, tal y como se describe en Seleccionar un modelo de subprocesos múltiples para su proyecto (más arriba). Ya no es necesario suprimir toda la interacción con el usuario (la opción Ejecución desatendida) para tener una DLL con separación de procesos.

Cuando crea una instancia de un formulario en tiempo de ejecución, Visual Basic sigue las mismas reglas que utiliza para otros objetos privados. Es decir, el nuevo formulario se crea en el subproceso donde se ejecuta el operador New. Si crea un formulario implícitamente (por ejemplo, si tiene acceso a una propiedad de formulario mediante una variable que se declaró como As New Form1), el formulario se creará en el subproceso donde se ejecuta el código.

Nota   Un caso especial de creación implícita de formulario es el Id. predeclarado (por ejemplo, Form1), una variable de formulario global oculta que Visual Basic mantiene para cada clase de formulario. Puesto que Visual Basic duplica los datos globales para cada apartado, hay un Form1 distinto para cada subproceso. Para evitar confusiones, puede resultar útil evitar el uso de Id. predeclarados en componentes con separación de subprocesos si declara explícitamente su propias variables de formulario.

Nota   Duplicar los datos globales significa que una variable declarada como Public en un módulo estándar sólo es global para el subproceso; cada subproceso tiene una instancia de la variable. También significa que las propiedades del objeto App, como App.ThreadID, tienen instancias distintas para cada subproceso.

A diferencia de los formularios, los controles ActiveX son objetos públicos que los formularios cliente pueden crear y utilizar. Una instancia de un control ActiveX siempre reside en el mismo subproceso que el del formulario cliente que la utiliza.

Importante   En una DLL con modelo de separación de procesos se crea un nuevo apartado para cada subproceso cliente que solicita objetos proporcionados por la DLL. La primera vez que un subproceso cliente solicita un objeto de ese tipo se ejecuta la subrutina Sub Main para el nuevo apartado. Una DLL no puede crear subprocesos propios.

 

Cambios a "Diseñar componentes de subprocesos múltiples fuera de proceso"

Ya no es necesario suprimir toda la interacción de usuario (la opción Ejecución desatendida) para tener un Exe de múltiples subprocesos. Las descripciones de Subproceso por objeto y Conjunto de subprocesos (subprocesos circulares) siguen siendo las mismas.

Puede hacer que un proyecto Exe ActiveX tenga separación de subprocesos si abre la ficha General del cuadro de diálogo Propiedades del proyecto y, a continuación, selecciona Subproceso por objeto o Conjunto de subprocesos y establece un tamaño de conjunto mayor que uno.

Al igual que otros objetos privados, los formularios residen en el subproceso donde se crearon. No es posible crear objetos privados mediante la función CreateObject, por lo que no se pueden utilizar para iniciar nuevos subprocesos.

Importante   En un ejecutable de subprocesos múltiples, la subrutina Sub Main se ejecuta de manera independiente para cada nuevo subproceso. Visual Basic no proporciona ninguna manera de determina qué subproceso se creó en primer lugar.

 

Escenarios de usuario

Los siguientes temas describen escenarios en los que puede que desee utilizar el modelo de separación de subprocesos.

Controles con separación de subprocesos para Internet Explorer 4.0
Crear una DLL segura para los subprocesos con formularios
Crear una aplicación de subprocesos múltiples de prueba

 

Controles con separación de procesos para Internet Explorer 4.0

Internet Explorer 4.0 muestra ventanas mediante varios subprocesos de ejecución. Cuando dos ventanas diferentes de Internet Explorer 4.0 muestran instancias del mismo control ActiveX, el OCX debe proporcionar una instancia a cada subproceso. Si ambas instancias se proporcionan desde el mismo apartado del OCX (como es el caso de Visual Basic 5.0), una de las instancias del control sufrirá una degradación de rendimiento debido a la ordenación entre subprocesos.

Además de la degradación de rendimiento, un control de un único subproceso puede provocar problemas con el enfoque, el cambio con la tecla TAB y las teclas de acceso cuando se utilizan en aplicaciones de subprocesos múltiples.

La compilación de su OCX con Visual Basic versión 5.0 Service Pack 2 mejora el rendimiento y elimina estos problemas. Cada instancia del control utilizada por Internet Explorer 4.0 se ejecuta en el mismo subproceso que la ventana que muestra el control, ya que el OCX puede admitir un apartado diferente para cada subproceso cliente.

La mayoría de los controles ActiveX que se entregan con Visual Basic se han actualizado

Visual Basic versión 5.0 Service Pack 2 incluye nuevas versiones de la mayoría de los controles ActiveX que se suministraban con Visual Basic 5.0. Los controles actualizados ahora tienen el modelo de separación de subprocesos y funcionarán igualmente bien sobre clientes de un único subproceso o de subprocesos múltiples. Entre los controles que todavía son de un único subproceso se incluyen DBGrid, MSChart y los controles heredados que se incluían en el directorio Tools de Visual Basic 5.0.

Controles ActiveX creados con Visual Basic

Una vez que haya aplicado Visual Basic versión 5.0 Service Pack 2, los nuevos proyectos de control ActiveX serán de manera predeterminada del modelo de separación de subprocesos. Puede agregar separación de subprocesos a un control ActiveX ya existente si cambia el modelo de subprocesos, tal y como se describe en Seleccionar un modelo de subprocesos múltiples para su proyecto, y vuelve a compilar el proyecto. Para muchos proyectos de control ActiveX, esto es todo lo que necesita realizar.

Si su proyecto de control ActiveX utiliza controles componentes de un único subproceso, el intento de cambiar el Modelo de subprocesos a Separación de subprocesos provocará un error. Debido al número y a la gravedad de los problemas que causan los controles ActiveX de un único subproceso para los clientes de subprocesos múltiples, Visual Basic no permite utilizarlos como componentes de controles ActiveX con separación de subprocesos. Esto se explica en Convertir proyectos ya existentes.

Si tiene controles ActiveX ya existentes que emplean controles componentes de un único subproceso, póngase en contacto con su proveedor para ver si existe una versión con separación de procesos.

En Convertir proyectos ya existentes se explican otras consideraciones de diseño para los controles ActiveX con separación de procesos.

 

Crear una DLL segura para los subprocesos con formularios

Ahora puede establecer la opción Modelo de subprocesos a Separación de subprocesos en los proyectos de DLL ActiveX que contienen formularios.

Las DLL con separación de procesos no pueden crear su propios subprocesos; la primera vez que un subproceso cliente solicita un objeto proporcionado por su DLL, se crea un nuevo apartado y se ejecuta la subrutina Sub Main para ese apartado. Todos los objetos públicos que solicite ese cliente residirán en el mismo apartado y compartirán datos globales. Cualquier objeto privado (incluyendo los formularios) creado por los objetos públicos también residirá en el apartado.

Visual Basic no proporciona ninguna manera para que los apartados sean conscientes de que existen otros apartados. Sin embargo, un cliente de subprocesos múltiples podría obtener una referencia a un objeto del subproceso A y pasarla a un objeto del subproceso B. Si su DLL permite esto, debe leer la información sobre la reentrada en la sección "Modelo de separación de subprocesos en Visual Basic" de los Libros en pantalla, y en Cambios a "Modelo de separación de subprocesos en Visual Basic" en este mismo documento.

Importante   Los formularios modales mostrados por un subproceso no bloquean la ejecución de código de otros subprocesos y no son modales para los formularios de otros subprocesos. Al mostrar un formulario se produce un control, tal y como ocurre al llamar a DoEvents, y por tanto puede hacer que se vuelva a entrar en el código de un objeto.

 

Crear una aplicación de subprocesos múltiples de prueba

Aplicar Service Pack 2 a las ediciones Profesional y Empresarial de Visual Basic le permite crear aplicaciones de subprocesos múltiples de prueba para practicar con sus controles de subprocesos múltiples. Los pasos para crear una aplicación sencilla de subprocesos múltiples son los siguientes:

  1. Abra un nuevo proyecto EXE ActiveX y asigne nombre al módulo de clase predeterminado MainApp. Configure la propiedad Instancing de MainApp como PublicNotCreatable. Un objeto MainApp ocupará el primer subproceso de la aplicación y mostrará la interfaz de usuario principal.
  2. En la ficha General del cuadro de diálogo Propiedades del proyecto, seleccione Sub Main en el cuadro Objeto de inicio, seleccione Subproceso por objeto en el cuadro Modelo de subprocesos y escriba un valor único para el nombre del proyecto. (El nombre del proyecto determina el nombre de la biblioteca de tipos; pueden ocurrir problemas si dos aplicaciones tienen el mismo nombre de la biblioteca de tipos.) "ThreadDemo" es el nombre de proyecto que se utiliza en el ejemplo siguiente. En la ficha Componente, seleccione Independiente en el cuadro Modo de inicio.
  3. Agregue un formulario, llámelo frmProcess, y asigne a las propiedades Visible y ControlBox el valor False. Este formulario funciona como una ventana oculta, que Sub Main usará para identificar el subproceso principal del proceso. No se necesita código para este formulario.
  4. Agregue un módulo estándar al proyecto. En este módulo, coloque las declaraciones, el procedimiento Sub Main y el procedimiento EnumThreadWndMain que se muestra más abajo. Tal y como se explica en el texto que lo acompaña y en los comentarios del código, Sub Main se ejecutará cuando se inicie su aplicación y cada vez que cree un nuevo subproceso. El código de ejemplo de Sub Main muestra cómo se identifica el primer subproceso, de forma que sepa cuándo crear MainApp.
  5. Agregue un formulario y llámelo frmMTMain. Este formulario proporciona la interfaz de usuario principal de la aplicación de prueba. Agregue al formulario la declaración y el evento Form_Unload inmediatamente anterior al título "Varias instancias de la aplicación de prueba".
  6. En el procedimiento de evento Class_Initialize de MainApp, agregue código para que se muestre frmMTMain. El código se proporciona más abajo.
  7. Para crear subprocesos de prueba adicionales debe tener en su proyecto al menos una clase cuya propiedad Instancing tenga el valor MultiUse. Agregue un módulo de clase y un formulario e inserte el código que se proporciona bajo el título "Crear nuevos subprocesos". Puesto que para este proyecto seleccionó Subproceso por objeto, cada objeto público que se cree externamente se iniciará en un nuevo subproceso. Esto significa que puede crear un nuevo subproceso mediante la función CreateObject para crear una instancia de su clase MultiUse a partir del Id. de programa (ProgID), tal y como se explica en el texto que lo acompaña.
  8. Agregue código a frmMTMain para crear nuevos subprocesos mediante la creación de instancias de las clases MultiUse que definió. En el ejemplo siguiente, vea el código que hay bajo el título "Crear nuevos subprocesos".
  9. El entorno de desarrollo no admite subprocesos múltiples. Si presiona F5 para ejecutar el proyecto, todos los objetos se crearán en el mismo subproceso. Para poder probar el comportamiento de subprocesos múltiples debe compilar el proyecto EXE ActiveX y ejecutar el archivo ejecutable resultante.

Importante   Para asegurar que cada nuevo objeto MultiUse inicia un nuevo subproceso, debe usar Subproceso por objeto, en lugar de Conjunto de subprocesos.

Determinar el subproceso principal durante la ejecución de Sub Main

Sub Main se ejecuta para cada nuevo subproceso. La razón es que Visual Basic mantiene una copia distinta de sus datos globales para cada subproceso (cada apartado). Para poder inicializar los datos globales para el subproceso, debe ejecutarse la subrutina Sub Main. Esto significa que si Sub Main carga un formulario oculto o muestra la interfaz principal de usuario de su aplicación, se cargarán nuevas copias de esos formularios para cada nuevo subproceso que cree.

El código siguiente determina si Sub Main se está ejecutando en el primer subproceso, de forma que pueda cargar el formulario oculto una sola vez y mostrar la interfaz principal de usuario de la aplicación de prueba sólo una vez.

' Valor raíz para el título de ventana oculta
Public Const PROC_CAPTION = "ApartmentDemoProcessWindow"

Public Const ERR_InternalStartup = &H600
Public Const ERR_NoAutomation = &H601

Public Const ENUM_STOP = 0
Public Const ENUM_CONTINUE = 1

Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Declare Function EnumThreadWindows Lib "user32" (ByVal dwThreadId As Long, ByVal lpfn As Long, ByVal lParam As Long) As Long

' Controlador de ventana recuperado por EnumThreadWindows.
Private mhwndVB As Long
' Formulario oculto que se utiliza para identificar el subproceso principal.
Private mfrmProcess As New frmProcess
' Id. de proceso
Private mlngProcessID As Long

Sub Main()
    Dim ma As MainApp

    ' Toma prestado un controlador de ventana que usa para obtener el Id.
    '   de proceso (vea la devolución de llamada EnumThreadWndMain, más adelante).
    Call EnumThreadWindows(App.ThreadID, AddressOf EnumThreadWndMain, 0&)
    If mhwndVB = 0 Then
        Err.Raise ERR_InternalStartup + vbObjectError, , "Error interno al iniciar el subproceso"
    Else
        Call GetWindowThreadProcessId(mhwndVB, mlngProcessID)
        ' El Id. de proceso hace que el título de la ventana oculta sea único.
        If 0 = FindWindow(vbNullString, PROC_CAPTION & CStr(mlngProcessID)) Then
            ' La ventana no se encontró, por lo que es el primer subproceso.
            If App.StartMode = vbSModeStandalone Then
                ' Crea un formulario oculto con un título único. 
                mfrmProcess.Caption = PROC_CAPTION & CStr(mlngProcessID)
                ' El evento Initialize de MainApp (Instancing =
                '   PublicNotCreatable) muestra el interfaz de usuario principal.
                Set ma = New MainApp
                ' (El cierre de la aplicación es más sencillo si no hay ninguna
                '   referencia global a MainApp; en su lugar, MainApp
                '   debe pasar Me al formulario de usuariio principal, de forma
                '   que el formulario evite la terminación de MainApp.)
            Else
                Err.Raise ERR_NoAutomation + vbObjectError, , _
                    "La aplicación no se puede iniciar con Automatización"
            End If
        End If
    End If
End Sub

' Función de devolución de llamada utilizada por EnumThreadWindows.
Public Function EnumThreadWndMain(ByVal hwnd As Long, ByVal lParam As Long) As Long
    ' Guarda el controlador de ventana.
    mhwndVB = hwnd
    ' La primera ventana es la única que se requiere.
    ' Detiene la iteración tan pronto como se encuentra una ventana.
    EnumThreadWndMain = ENUM_STOP
End Function

' MainApp llama a esta rutina Sub en su evento Terminate;
'   de lo contrario, el formulario oculto impide que
'   se cierre la aplicación.
Public Sub FreeProcessWindow()
    Unload mfrmProcess
    Set mfrmProcess = Nothing
End Sub

Importante   Esta técnica para identificar el primer subproceso puede que no funcione en futuras versiones de Visual Basic.

Tenga en cuenta que Sub Main no realiza ninguna acción para ningún subproceso posterior al primero. Cuando agregue código que cree objetos MultiUse (para poder iniciar subprocesos siguientes), asegúrese de incluir código para inicializar esos objetos.

EnumThreadWindows se utiliza con una devolución de llamada, EnumThreadWndMain, para encontrar una de las ventanas ocultas que Visual Basic crea para su uso interno. El controlador de esta ventana oculta se pasa a GetWindowThreadProcessId, que devuelve el Id. de proceso. El Id. de proceso se utiliza entonces para crear un título único para la ventana oculta (frmProcess) que carga Sub Main. Los subprocesos siguientes detectan esta ventana y de esta manera pueden indicar que no necesitan crear el objeto MainApp. Estos giros son necesarios ya que Visual Basic no proporciona ninguna manera de identificar el subproceso principal de la aplicación.

La clase MainApp, en su evento Initialize, muestra el formulario principal de la aplicación de prueba. MainApp debe pasar al formulario principal su referencia Me, de manera que el formulario evita que MainApp termine. Desde la interfaz principal de usuario puede crear todos los subprocesos siguientes. Configurar la propiedad Instancing para MainApp como PublicNotCreatable le ayudará a evitar que se muestren dos formularios de interfaz de usuario principal.

Un ejemplo sencillo de una clase MainApp y su formulario asociado (pasos 5 y 6 anteriores) podría tener la apariencia siguiente:

' Código para una clase MainApp.
Private mfrmMTMain As New frmMTMain

Private Sub Class_Initialize()
    Set mfrmMTMain.MainApp = Me
    mfrmMTMain.Caption = mfrmMTMain.Caption & " (" & App.ThreadID & ")"
    mfrmMTMain.Show
End Sub

Friend Sub Closing()
    Set mfrmMTMain = Nothing
End Sub

Private Sub Class_Terminate()
    ' Borra la ventana oculta.
    Call FreeProcessWindow
End Sub

' Código para el formulario frmMTMain.
Public MainApp As MainApp

Private Sub Form_Unload(Cancel As Integer)
    Call MainApp.Closing
    Set MainApp = Nothing
End Sub

Varias instancias de la aplicación de prueba

Incluir el Id. de proceso en el título de la ventana oculta permite que se ejecuten varias instancias de la aplicación de prueba sin interferirse entre ellas.

Cuando llama a CreateObject, la instancia de la clase pública que crea estará en un subproceso de la instancia actual de la aplicación. Esto se debe a que CreateObject siempre intenta crear un objeto en la aplicación actual antes de buscar otros componentes Exe que podría proporcionar el objeto.

Propiedades útiles para el apartado

Puede que encuentre útil exponer el Id. de proceso como una propiedad de sólo lectura del módulo que contiene Sub Main:

'Este código no se requiere para la aplicación de prueba
Public Property Get ProcessID() As Long
    ProcessID = mlngProcessID
End Property

Esto permite que cualquier objeto del subproceso obtenga el Id. de proceso si llama a la propiedad ProcessID no cualificada. También puede que encuentre útil exponer una propiedad Boolean IsMainThread de esta forma.

Crear nuevos subprocesos

La opción Subproceso por objeto hace que cada objeto público se cree externamente (es decir, que se cree mediante la función CreateObject) para iniciarse en un nuevo subproceso. Para crear un nuevo subproceso, basta con utilizar el Id. de programa (ProgID) de una de sus clases MultiUse:

'Este código no se incluye en la aplicación de prueba
Dim tw As ThreadedWindow
Set tw = CreateObject("ThreadDemo.ThreadedWindow")

La variable tw contiene ahora una referencia a un objeto de un nuevo subproceso. Todas las llamadas a las propiedades y los métodos de este objeto que se realicen mediante tw estarán sujetas a la carga adicional que supone la ordenación entre subprocesos.

Nota   Un objeto creado con el operador New no se crea en un nuevo subproceso. Reside en el mismo subproceso donde se ejecutó el operador New. Vea "Diseñar componentes de subprocesos múltiples fuera de proceso" y "Cómo funciona la creación de objetos en componentes de Visual Basic" de los Libros en pantalla.

Para asegurarse de que MainApp no termina hasta que todos los demás subprocesos han finalizado, puede asignar a cada clase pública una propiedad MainApp. Cuando un objeto crea un objeto MultiUse en un nuevo subproceso, puede pasar al nuevo objeto una referencia al objeto MainApp como parte del proceso de inicialización. (También puede pasar a MainApp una referencia al nuevo objeto, de forma que MainApp tenga un conjunto de referencias a todos los objetos que controlan subprocesos; sin embargo, recuerde que esto creará referencias circulares. Vea "Tratamiento de las referencias circulares" en los Libros en pantalla.)

Si desea que una clase que controla un subproceso muestre un formulario, debe proporcionarle un método Initialize (no se confunda con el evento Initialize) o un método Show que muestre el formulario. No muestre el formulario en el procedimiento de evento Class_Initialize, puesto que esto podría provocar error de temporización al crear instancias de la clase. En una clase muy sencilla, el código para una clase MultiUse ThreadedWindow y su formulario, frmThreadedWindow, podría tener la siguiente apariencia:

'Código para una clase MultiUse ThreadedWindow.
Private mMainApp As MainApp
Private mfrm As New frmThreadedWindow

Public Sub Initialize(ByVal ma As MainApp)
    Set mMainApp = ma
    Set mfrm.ThreadedWindow = Me
    mfrm.Caption = mfrm.Caption & " (" & App.ThreadID & ")"
    mfrm.Show
End Sub

Friend Sub Closing()
    Set mfrm = Nothing
End Sub

'Código para el formulario frmThreadedWindow.
Public ThreadedWindow As ThreadedWindow

Private Sub Form_Unload(Cancel As Integer)
    Call ThreadedWindow.Closing
    Set ThreadedWindow = Nothing
End Sub

El siguiente miniprograma muestra cómo podría inicializar el objeto ThreadedWindow:

'Código para el formulario principal de la aplicación de prueba (frmMTMain).
Private Sub mnuFileNewTW_Click()
    Dim tw As ThreadedWindow
    Set tw = CreateObject("ThreadDemo.ThreadedWindow")
    ' Indica al nuevo objeto que muestre su formulario y
    '   le pasa una referencia al objeto de la 
    '   aplicación principal.
    Call tw.Initialize(Me.MainApp)
End Sub

Si tiene varias clases que controlan subprocesos, puede hacer que su código sea más genérico mediante la definición de una interfaz IApartment que contenga el método Initialize. Cuando implemente IApartment en cada clase, puede proporcionar el código del método Initialize apropiado para esa clase. El código para la creación de subproceso podría tener la siguiente apariencia:

'Este código no se requiere para la aplicación de prueba
Private Sub mnuFileNewObject_Click(Index As Integer)
    Dim iapt As IApartment
    Select Case Index
      Case otThreadedWindow
        Set iapt = CreateObject("ThreadDemo.ThreadedWindow")
      ' (otros casos…)
    End Select
    ' Código común para inicializar objetos.
    Call iapt.Initialize(MainApp)
End Sub

Nota   Puede crear una interfaz IXxxxApartment que sea conocida sólo para la aplicación de subprocesos múltiples si define la interfaz en una biblioteca de tipos distinta. En el proyecto de Exe ActiveX, establezca una referencia a la biblioteca de tipos.

Mantener referencias a objetos de subprocesos múltiples

Para asegurar el cierre apropiado de una aplicación de subprocesos múltiples debe hacer un seguimiento de todas las referencias a los objetos MultiUse que utilice para crear y controlar subprocesos.

Defina claramente sus objetivos para la duración del objeto. Por ejemplo, considere el caso de un objeto MultiUse que muestra un formulario. La forma más sencilla de administrar la duración del objeto es hacer que el objeto pase al formulario una referencia Me; el formulario mantiene entonces el objeto vivo. Cuando el usuario cierra el formulario, el evento Unload del formulario debe establecer todas las referencias al objeto MultiUse como Nothing, de forma que el objeto puede terminar y a su vez limpiar su referencia al formulario. (Puede que encuentre útil proporcionar al objeto MultiUse un método Friend que limpie la referencia al formulario y todas las demás referencias internas al objeto; el evento Unload del formulario puede llamar a este método.)

Si el objeto que controla un subproceso crea objetos adicionales en el subproceso mediante el operador New, asegúrese de que limpia las referencias a esos objetos. El subproceso no puede cerrarse hasta que se hayan liberado todas las referencias a objetos que se crearon en el subproceso. Los subprocesos abiertos consumen recursos del sistema.

Los métodos Friend no se pueden usar entre subprocesos

Puesto que las propiedades y métodos Friend no forman parte de la interfaz pública de una clase, no puede llamarlos desde otro subproceso. Las llamadas de subprocesos cruzados entre objetos se limitan a las propiedades y los métodos declarados como Public.

Reentrada

Si un método de un objeto funciona llamando a DoEvents, mostrando un formulario modal o haciendo una llamada secundaria a un objeto de otro subproceso, una segunda llamada puede entrar en el código del método antes de que se complete la primera llamada. Si ese método usa o cambia valores de propiedad o variables de módulo, esto podría dar lugar a un estado interno no válido del objeto. Para protegerse frente a la reentrada, puede hacer lo siguiente:

  • Evitar cesiones.
  • Mantener un indicador Boolean de módulo para cada método. Cuando comience un método, comprueba este indicador para determinar si hay en curso una llamada al método. Si no la hay, el método asigna al indicador el valor True y continúa; de lo contrario, produce un error. Debe tener cuidado de volver a asignar el valor False al indicador cuando se complete el método o cuando se salga por cualquier razón.
  • Escribir métodos de reentrada; es decir, métodos que no dependen de datos de módulo.

Tareas asíncronas

Visual Basic no proporciona ninguna manera de bifurcar la ejecución; es decir, hacer que un subproceso inicie una llamada a un método en un nuevo subproceso y reanude inmediatamente el procesamiento en el subproceso original. Puede simular este comportamiento en su aplicación de prueba si hace que la llamada al método original active un cronómetro y después vuelva inmediatamente. Cuando ocurra el evento del cronómetro, puede desactivar el cronómetro y realizar el procesamiento asíncrono. Esta técnica se explica en "Devoluciones de llamada y eventos asíncronos" en los Libros en pantalla, y se demuestra en los Libros en pantalla (vea "Crear un componente Exe ActiveX") y en la aplicación de ejemplo Coffee.

Usar la aplicación de subprocesos múltiples de prueba

Debe compilar la aplicación de prueba de subprocesos múltiples para poder probar el componente con separación de subprocesos, ya que el entorno de desarrollo de Visual Basic no admite actualmente varios subprocesos de ejecución. Si tiene Visual Studio, puede que encuentre útil compilar la aplicación de prueba con la información para depuración de código nativo, de forma que pueda utilizar el depurador de Visual Studio.

 

Nota sobre las secuencias de comandos seguras para controles ActiveX

Dos de los controles con separación de subprocesos que se incluyen con Visual Basic versión 5.0 Service Pack 2, el control Common Dialog y el control Toolbar, admiten ahora la interfaz IObjectSafety de ActiveX. Cuando se utilizan estos controles en un entorno donde se exigen secuencias de comandos seguras, como en Internet Explorer, se marcan como Seguros para secuencias de comandos; sin embargo, ciertas características de estos controles estarán desactivadas para poder calificarlos como seguros para secuencias de comandos:

  • El control Toolbar no puede guardar su estado en el registro, puesto que una secuencia de comandos con un comportamiento defectuoso podría explotarlo para escribir información descontrolada en el registro.
  • Mostrar ayuda está desactivado en el control Common Dialog, ya que una secuencia de comandos con un comportamiento defectuoso podría usar esta característica para ejecutar macros de Ayuda que podrían provocar daños al equipo del usuario.

 

Lista de componentes

En Visual Basic versión 5.0 Service Pack 2 se incluyen los siguientes archivos: 

comct232.ocx
comct232.dep
comctl32.ocx
comctl32.dep
comdlg32.ocx
comdlg32.dep
dbgrid32.ocx
dbgrid32.dep
dblist32.ocx
dblist32.dep
mci32.ocx
mci32.dep
mscomm32.ocx
mscomm32.dep
msflxgrd.ocx
msflxgrd.dep
msinet.ocx
msinet.dep
msmapi32.ocx
msmapi32.dep
msmask32.ocx
msmask32.dep msrdc20.ocx
msrdc20.dep
msrdo20.dll
msrdo20.dep
msstkprp.dll
mswinsck.ocx
mswinsck.dep
picclp32.ocx
picclp32.dep
richtx32.ocx
richtx32.dep
sysinfo.ocx
sysinfo.dep
tabctl32.ocx
tabctl32.dep
vb5.exe
vba5.dll
vb5ide.dll
msvbvm50.dll
c2.exe
asycfilt.dll
oleaut32.dll
olepro32.dll
stdole2.tlb
setupwiz.exe
vb5dep.ini
setup1.bas
setup1.exe
vb5sp2.htm
vb5sp2.wri
readme.wri
mscdrun.dll
mscdrun.dep
mscondes.dll
msctles.dll
cmdlges.dll
flxgdes.dll
msprpes.dll
vb5es.dll

 


la Luna del Guille o... el Guille que está en la Luna... tanto monta...

Pulsa este link si quieres ver el resultado de buscar: VB5FixlistSP2 en http://www.microsoft.com/kb