¿Los controles en VCL admiten directamente subprocesos múltiples?
Porque el programa que escribes está en modo exclusivo, no en un hilo de aplicación. Cuando Rising es antivirus, al hacer clic en otros menús todavía responde, porque el proceso antivirus está en otro hilo. WIN 98/NT/2000/XP es un sistema operativo multitarea, es decir: un proceso se puede dividir en varios hilos, cada uno de ellos. Los subprocesos se turnan para ocupar el tiempo de ejecución y los recursos de la CPU, o en otras palabras, el tiempo de la CPU se divide en porciones y cada porción se asigna a un subproceso diferente. De esta manera, cada subproceso se "suspende" y "desperta" por turnos. Dado que el intervalo de tiempo es muy pequeño, da la impresión de que se están ejecutando simultáneamente.
La siguiente es información que encontré para su referencia:
El subproceso múltiple brinda los siguientes beneficios: (Léalo usted mismo)
1) Evite cuellos de botella
2) Operaciones paralelas;
3) Mejorar la eficiencia
En subprocesos múltiples, a través de la gestión de prioridades, los programas importantes se pueden operar primero, lo que mejora; eficiencia.
Flexibilidad en la gestión de tareas.
Por otro lado, en un sistema multi-CPU, se pueden ejecutar diferentes subprocesos en diferentes CPU,
para manejar realmente múltiples tareas al mismo tiempo (Win 98 solo es simulado , Y Win/NT/2000 es cierto
varias CPU funcionan simultáneamente).
Dos conceptos de multithreading:
1) Proceso: también llamado tarea, el programa carga la memoria y asigna recursos, lo que se llama "un proceso
". Nota: No es necesario que el proceso en sí se esté ejecutando. El proceso consta de las siguientes partes:
a>Un espacio de direcciones privado, que es un conjunto de espacios de direcciones de memoria virtual que el proceso puede usar;
b>El código relevante y datos de la fuente del programa;
c>Recursos del sistema, como objetos de sincronización del sistema operativo, etc.;
d>Contiene al menos un hilo (hilo principal);
2) Hilo: Es la unidad de ejecución del programa (el hilo en sí no incluye el código del programa, el proceso en realidad posee el código. Cada proceso incluye al menos un hilo, llamado hilo principal, y un hilo). proceso
Si hay varios subprocesos, pueden compartir los recursos del mismo proceso y ejecutarse simultáneamente.
Un subproceso es una unidad de ejecución de un proceso y la entidad básica para que el sistema operativo asigne tiempo de CPU.
Un subproceso consta principalmente de las dos partes siguientes:
a>Estructura de datos;
b>Registros y pila de CPU;
Los subprocesos de un proceso pueden ejecutarse de forma independiente o controlar la ejecución de otro subproceso.
Tenga en cuenta:
No se puede abusar del subproceso múltiple. En el libro (lectura propia) se mencionan varias deficiencias del subproceso múltiple.
2-2 Objeto Tthread
Aunque Windows proporciona una cantidad relativamente grande de funciones API para el diseño de subprocesos múltiples, es extremadamente inconveniente usar las funciones API directamente
Conveniente y propenso a errores si se usa incorrectamente. Para resolver este problema,
Borland Company tomó la iniciativa en el lanzamiento de un objeto Tthread para resolver las dificultades en el diseño de subprocesos múltiples y
simplificar el manejo de problemas de subprocesos múltiples.
Cabe señalar que el objeto Tthread no tiene una instancia. Su comunicación con la interfaz se basa principalmente en
el formulario principal (subproceso VCL principal), que es algo diferente de. el uso de otros objetos.
1. Métodos principales del objeto Tthread
Construir hilo:
constructor Create(CreateSuspended:boolean)
Entre ellos: CreateSuspended= true Construir pero no despertar
false Despertar mientras se construye
También puedes usar el siguiente método
Create heredado(CreateSuspended:boolean)
Suspender el hilo:
suspender
(aumentar el número de veces que se suspende el hilo)
Desactivar el hilo:
resume
(Nota: tenga en cuenta que este atributo reduce en uno el número de veces que se suspende el hilo. Cuando el número es 0,
se despierta. En otras palabras, ¿cómo cuántas veces se cuelga el hilo, cuántas veces se activa cuando se suspende
al mismo tiempo, el puntero de dirección del hilo permanecerá sin cambios, por lo que cuando el hilo se despierte después de la suspensión. comenzará a ejecutarse desde el lugar donde fue suspendido
)
Destrucción (borrar la memoria ocupada por el hilo):
destruir
Terminar el hilo (se discutirá en detalle más adelante):
Terminar
2. Ejemplo simple de aplicación de hilo:
A continuación se utiliza un ejemplo para ilustrar la aplicación del método anterior. Sabemos que los bucles son uno de los modos de operación más exclusivos. Ahora esperamos establecer dos objetos de hilo para realizar la operación de bucles en paralelo. El método específico es el siguiente:
Archivo---Nuevo---Objeto de hilo
Esto crea automáticamente una unidad de hilo en el formulario principal (escriba el nombre del hilo en el cuadro de diálogo
carácter), el nombre predeterminado es Unidad2. Cree la segunda unidad de subproceso Unit3 de la misma manera.
Cabe señalar que existe un proceso determinado en la Unidad2 y la Unidad3:
procedimiento Objeto.Execute;
comenzar
finalizar ;
El programa se ejecuta automáticamente después de que el hilo se activa. También puede llamar a otros procedimientos y funciones personalizados en él.
El final de este proceso significa el final del programa del hilo.
Para construir un hilo, defina un proceso de construcción en el área Tipo de la interfaz:
tipo
Objeto = clase(TThread) / / Se da automáticamente, también puedes cambiarlo directamente
privado
protegido
procedimiento Ejecutar anulación;
público
constructor create; //Escrito por mí
Y escribe en el área de implementación:
constructor Object.create;
comenzar
heredado create(true );
end
Donde Objeto es el nombre del objeto del hilo. Entonces, cuando escribo esto, espero llamar a este proceso de construcción en el formulario principal
.
El parámetro de Create() es Verdadero, lo que indica que el hilo construido está en estado suspendido.
Tenga en cuenta que en el mismo objeto de hilo, si se construye dos veces, se generarán dos hilos independientes. No solo las operaciones son independientes, sino que también se utilizan las variables locales de los hilos. Pero
Para simplificar el problema aquí, todavía se establecen dos objetos de subproceso independientes y los dos números de ciclo
son diferentes. Es fácil juzgar que son dos subprocesos diferentes. durante las operaciones paralelas.
Supongamos que nombramos los dos objetos hilo:
mymath1
mymath2
De esta manera, en la Unidad1, la siguiente declaración debería ser hecho:
implementación
usa unidad2, unidad3;
var thread1:mymath1;
thread2:mymath2;
De esta manera, en el hilo principal, se puede llamar al método del hilo correspondiente a través de estas dos variables del hilo.
El método para construir un hilo en el área del hilo principal es:
thread1:=mymath1.create;
thread2:=mymath2.create; p>
Suspender:
thread1.suspend;
thread2.suspend;
Despertar:
thread1.resume;
thread2.resume;
Destrucción:
thread1.destroy;
thread2.destroy
Explicación se necesita aquí La cuestión es que, dado que la unidad de subproceso necesita llamar al control de edición (objeto) del formulario,
Puedes usar dos métodos:
1) Definir un objeto TEdit en la unidad de hilo, por ejemplo
edit4:Tedit;
Referencia directa en el proceso Ejecutar
Pero en la Unidad1 se debe realizar una asignación en el FormCreate. proceso:
procedimiento TForm1.FormCreate(Remitente: TObject);
comenzar
thread1.edit4:=edit1;
finalizar;
De esta manera, conecte edit4 del primer hilo con edit1 en el formulario.
2) En el segundo hilo, primero declara la llamada a Unti1, es decir, agrega
Uses Unit1;
De esta manera, puedes llamar directamente Unti1 en la unidad de hilo Llama al control del Formulario principal, por ejemplo en Unidad3
Puedes escribir:
form1.edit2.text:=inttostr(i)
Comprenda estos conceptos básicos. Si sigue las reglas, podrá escribir programas multiproceso más complejos.
Otro punto a tener en cuenta es que la unidad de subproceso generada por defecto solo llama a una unidad:
Usa clases;
De esta manera, a menudo hay muchas funciones. y objetos No se puede utilizar en una unidad de subproceso, por lo que cuando sea necesario,
debe utilizar la unidad correspondiente según sea necesario. En aras de la simplicidad, esta rutina copia la mayoría de las unidades utilizadas comúnmente
., este no es un método recomendado porque causará demasiada basura en el programa, por lo que generalmente debes copiar lo que usas.
3. Funciones API de uso común
Cuando se trata de problemas de subprocesos múltiples, las funciones API proporcionadas por Windows también se utilizan con frecuencia:
El método encapsulado dentro del objeto Tthread en realidad se trata principalmente de llamar a funciones API. Sin embargo, es más completo y seguro. Al llamar directamente a funciones API, a menudo se producen algunos errores indebidos debido a un funcionamiento incorrecto
. Por lo tanto, personalmente creo que siempre que el método del objeto Tthread pueda resolver el problema, no llame a la función API directamente. La función API solo debe usarse cuando el método del objeto Tthread no puede resolver el problema.
Por ejemplo, cuando se llaman funciones API internamente en métodos de objetos Tthread, generalmente se usan los valores predeterminados
recomendados, pero cuando se necesita un control más preciso, las funciones API pueden ser utilizado directamente.
De hecho, el método del objeto Tthread ha sido reconocido por la mayoría de los programadores.
Por ejemplo, VB originalmente no tenía la capacidad de manejar directamente subprocesos múltiples, pero ahora. VB .Net anunció
que tiene la capacidad de manejar simplemente problemas de subprocesos múltiples, lo cual dice mucho.
La siguiente es una breve introducción a varias funciones de la API. Para mayor claridad y conveniencia, aquí el énfasis está en la explicación.
Para obtener descripciones correctas de las funciones, puede leer los ejemplos y manuales. en el libro usted mismo:
Hilo de compilación:
CreateThread(Parámetro 1, --atributo de seguridad (generalmente = Nil, atributo de seguridad predeterminado)
Parámetro 2, --Tamaño de la pila de subprocesos (generalmente = 0, la misma longitud que el subproceso principal
y se puede cambiar automáticamente según sea necesario)
Parámetro 3, --puntero al nombre de la función, @nombre de la función, este parámetro es diez
Es muy importante, si es incorrecto, la llamada no será exitosa.
Parámetro 4, el parámetro que el usuario debe pasar. al hilo, es un puntero a la estructura
y no es necesario pasar el parámetro, es
Parámetro 5): pasa algunos parámetros relacionados con los hilos. , por ejemplo:
CREATE_SUSPENDED crea un hilo suspendido;
0 Activar inmediatamente después de la creación.
El libro tiene ejemplos muy claros de la aplicación de esta función, puedes leerlo tú mismo.
Generalmente no se recomienda utilizar la función CreateTheard, pero se recomienda utilizar la función BeginTheard definida en la
unidad del sistema en la biblioteca RTL, porque no solo puede crear un hilo
Además de una función de entrada, se han agregado varias medidas de protección. Para obtener más información, consulte las instrucciones en la página 10 del libro
.
Las dos funciones API correspondientes a suspender (suspender) y reanudar (despertar) son:
Función SuspendThread(hThread:Thandle):DWORD;
Función ResumeThread(hThread:Thandle):DWORD;
Entre ellos, se requiere Thandle para controlar el identificador del hilo. Si la llamada a la función es exitosa, se devolverá el número de bloqueos.
La llamada no tuvo éxito. Luego se devuelve 0xFFFFFFFF.
4. Terminación y salida de hilos:
1) Salida automática:
Un hilo sale del proceso Execute(), lo que significa la terminación del mismo. thread, en este momento
Se llamará a la función ExitThread() de Windows para borrar la pila ocupada por el hilo.
Si la propiedad FreeOnTerminate del objeto del hilo se establece en True, el objeto del hilo
se eliminará automáticamente y se liberarán los recursos ocupados por el hilo.
Esta es la forma más sencilla de eliminar objetos de hilo.
2) Salida controlada:
Utilizando el atributo Terminar del objeto de hilo, la salida del hilo puede ser controlada por el proceso u otros hilos.
. Simplemente llame al método Terminate del hilo y establezca la propiedad Terminate del objeto del hilo en True.
En el hilo, el valor de Terminate debe monitorearse constantemente. Una vez que se encuentre que es Verdadero,
salga. Por ejemplo, en el proceso Execute(), puede escribir. así:
Mientras no termines,
comience
.........
finalice
3) Salir de la función API:
La declaración de la función API para la salida del subproceso es la siguiente: código
Función TerminateThread(hThread:Thandle;dwExitCode:DWORD); p>
Sin embargo, esta función El código finalizará inmediatamente, independientemente de si hay un mecanismo
intento....finalmente
en el programa, lo que puede provocar errores. Lo mejor es no utilizarlo a menos que sea un último recurso.
4) Utilice el método de suspender el hilo (suspend)
Utilice el método de suspensión del hilo suspendido, seguido de Libre, para liberar el hilo,
Por ejemplo:
thread1.suspend; //suspend
thread2.free; //release
Hay ejemplos correspondientes en el libro.
5. Prioridad de subprocesos:
En el caso de subprocesos múltiples, a los subprocesos generalmente se les debe dar la prioridad adecuada en función de la importancia de las tareas que realizan.
Generalmente, si varios subprocesos solicitan tiempo de CPU al mismo tiempo, se le dará prioridad al subproceso con mayor prioridad.
En Windows, la prioridad de los subprocesos se divide en 30 niveles, mientras que el objeto Tthread
en Delphi divide de manera relativamente simple la prioridad en siete niveles. Es decir, se declara un tipo de enumeración TTthreadPriority en Tthread:
type
TTthreadPriority(tpidle,tpLowest,tpLower,tpNormal,
tpHight, tpHighest, tpTimecrital)
corresponden al mínimo (efectivo cuando el sistema está inactivo, -15), inferior (-2), bajo
(-1), Normal (Normal 0), Alto ( 1), Superior (2), Superior (15).
Entre ellos, tpidle y tpTimecrital son algo especiales. Lea el contenido relevante del libro
para situaciones específicas.
Para establecer la prioridad, puede utilizar el atributo de prioridad del objeto de hilo:
threadObject.priority:=Tthreadpriority(level);
Aquí hay un demostración de subprocesos múltiples Ejemplos de prioridad:
2-3 Uso de subprocesos múltiples en la base de datos
1) Uso del modo ADO
Desde Delphi 6.0 El control de fuente de datos de ADO tiene capacidad de subprocesos múltiples incorporada, por lo que en el modo ADO, no necesita trabajar más para utilizar subprocesos múltiples. Utilice dos controles ADOTable para conectarse a dos bases de datos respectivamente y comuníquese con el control auxiliar de datos a través del control DataSource. De esta manera, puede darse cuenta de los problemas de la base de datos de manejo frontal y posterior.
2) Use el modo BDE y el objeto Tseeion
Si necesita usar el modo BDE y usar la base de datos con múltiples subprocesos, debe considerar el tema de la sesión
. En un solo hilo, la creación de cada fuente de datos genera automáticamente una Sesión.
Este es un archivo de información de base de datos privado para esta fuente de datos.
Sin embargo, los subprocesos múltiples deben administrarse de manera unificada, por lo que BDE proporciona especialmente un objeto Tsession, que puede administrar diferentes objetos de fuente de datos de la base de datos al mismo tiempo.
Las fuentes de datos de Databas pueden aceptar bases de datos de diferentes plataformas de datos.
Base de datos 1---databas(2)----table(Qurey)(3)---fuente de datos
|
|
|--------- Tsesión(1)
|
|
Base de datos 2--- databas(2)----table(Qurey)(3)---datasource
Método:
1) Tsession
Atributo: SessionName=nombre (Desde)
Activo=true (Activar)
2) Base de datos (puede tener varias)
Atributo: SessionName=Nombre de sesión
Dataname=Nombre (comenzando como el identificador de la Tabla)
AliasName=Alias de la Base de Datos
Connected=True (activado)
3) Tabla o Qurey
Atributo: SessionName=Nombre de sesión (no use el valor predeterminado)
DatabaseName=Si el nombre se da al frente, aparecerá el nombre de la base de datos
aquí.
Tablename=nombre de la tabla
Active=true (activar)
En el futuro, por ejemplo, agregar Datasoucre es lo mismo que otros, por lo que dos antes y después se puede construir
El sistema de gestión de bases de datos manejado por Taiwán.
2-4 Mecanismo de sincronización multiproceso
El mecanismo de sincronización es en realidad un mecanismo impulsado por eventos, lo que significa que el hilo generalmente está en un estado de "suspensión" y no estará desencadena a menos que ocurra un evento.
Por ejemplo, al copiar un archivo, después de que el hilo de copia completa un bloque de programa, activa la barra de proceso
El hilo llena una celda.
La necesidad de estudiar el mecanismo de sincronización de subprocesos múltiples es que cuando los subprocesos múltiples funcionan sincrónicamente, si
se llaman los mismos recursos al mismo tiempo, generalmente pueden ocurrir problemas. , leer no Hay un problema,
Sin embargo, si escribe (variables globales, base de datos), se producirán conflictos e incluso se producirán bloqueos mutuos y problemas de competencia.
1. Utilice el método Sincronizar
Este método se utiliza para acceder a los recursos administrados por el hilo principal de VCL. La aplicación de este método es:
Paso 1. : El código para acceder a la ventana principal (o recurso de control de la ventana principal) se coloca en un método del hilo;
El segundo paso: en el método Execute del objeto del hilo, a través del método Synchronize p>
Utilice este método.
Ejemplo:
procedimiento Teatro.Ejecutar;
comenzar
Sincronizar(actualizar
finalizar;
procedimiento Theatre.update;
inicio
.........
fin
Aquí, la actualización del método del hilo se sincroniza a través de Sincronizar.
2. Utilice el método Look de la clase VCL
Entre los componentes proporcionados por el IDE de Delphi, algunos objetos proporcionan mecanismos internos de sincronización de subprocesos
El subproceso de trabajo puede utilice directamente estos controles, como: Tfont, Tpen,
TBitmap, TMetafile, Ticon, etc. Además, un objeto de control muy importante llamado
TCanvas proporciona un método Lock para la sincronización de subprocesos. Cuando un subproceso usa este
objeto de control, primero llama a este método Lock y luego. opere el control
y luego llame al método Desbloquear para liberar el control del control.
Por ejemplo:
CanversObject.look;
intenta
Dibujar
finalmente
CanversObject.unlock;
end;
{Utilice este mecanismo de protección para garantizar que el desbloqueo se ejecutará independientemente de si hay una excepción o no
De lo contrario, es probable que se produzca la muerte. Bloquear. Al diseñar subprocesos múltiples, se debe prestar gran atención al problema de los bloqueos muertos
}
3. Método de espera
Cuando un subproceso debe esperar a otro. hilo para finalizar Cuando, puede llamar al método Waitfor.
Este método pertenece al objeto de hilo en espera. El prototipo del método Waitfor es el siguiente:
Función Waitfor(Const Astring:string):string;
thread1.resume;
thread1.waitfor;
thread2.resume; p> a la declaración que activa el hilo.
Entonces todos los hilos deben esperar a que el hilo1 termine de ejecutarse antes de poder ejecutarse, incluido el hilo principal
Se puede esperar que, dado que el hilo1 llama a Editar. control del formulario principal, entonces
Por qué, Edie1 no se mostrará mientras se ejecuta thread1.
Esto nos dice que dicho código no se puede utilizar como parte del hilo principal si
el hilo conectado al formulario principal espera a que finalice otro hilo, y otro hilo si usted. Si tienes que esperar
para acceder a la interfaz de usuario nuevamente, el programa puede estar bloqueado.
Ten cuidado al aplicar esto.