Red de conocimiento informático - Computadora portátil - ¿Cuándo se ejecuta el hilo principal de Delphi thread.execute?

¿Cuándo se ejecuta el hilo principal de Delphi thread.execute?

Antes de comprender los subprocesos múltiples, primero comprendamos la relación entre procesos y subprocesos.

Un programa tiene al menos un proceso principal y un proceso tiene al menos un subproceso.

El hilo principal también se llama hilo de UI.

La principal diferencia entre procesos y subprocesos es que son diferentes formas de gestionar los recursos del sistema operativo. El proceso tiene un espacio de direcciones independiente. Después de que un proceso falla, no afectará a otros procesos en modo protegido y los subprocesos son simplemente rutas de ejecución diferentes en un proceso. Los subprocesos tienen sus propias pilas y variables locales, pero no hay un espacio de direcciones separado entre subprocesos. La muerte de un subproceso equivale a la muerte de todo el proceso. Por lo tanto, los programas multiproceso son más robustos que los programas multiproceso. al cambiar de proceso, se consume mucho tiempo, los recursos son mayores y la eficiencia es menor. Pero para algunas operaciones concurrentes que requieren ejecución simultánea y compartir ciertas variables, sólo se pueden usar subprocesos, no procesos. Si estás interesado en profundizar más, te sugiero que eches un vistazo a "Sistemas Operativos Modernos" o "Diseño e Implementación de Sistemas Operativos". Está bastante claro sobre este tema.

El subproceso múltiple debería ser una habilidad básica para los programadores, pero nunca he aprendido esta habilidad básica, por lo que parece que solo la sé cuando entiendo 2+2, en realidad no sé 1+. 1.

Debería ser un artículo elocuente al principio, pero sigo recomendando hacerlo primero y comprenderlo intentándolo.

Pruebe esto primero:

procedimiento TForm1 .Button1Click(Remitente: TObject); var

i: Entero; comenzar

for i:= 0 a 500000 hacer

comenzar

Canvas.TextOut(10, 10, IntToStr(i));

end; end;

Cuando el programa anterior se está ejecutando, nuestro formulario está básicamente "muerto", puedes intente arrastrar el formulario mientras el programa se está ejecutando...

Delphi nos proporciona una forma sencilla (Application.ProcessMessages) de resolver este problema:

procedimiento TForm1.Button1Click(Sender: TObject); var

i: Entero; comenzar

for i:= 0 a 500000

comenzar

Canvas.TextOut( 10, 10, IntToStr(i));

Application.ProcessMessages;

end; end

Esta Application.ProcessMessages ; bucles, verificará y procesará otros mensajes en la cola de mensajes primero.

Pero esto no se considera multiproceso. Por ejemplo: si arrastra el formulario durante la operación, el bucle se detendrá...

Antes de usar subprocesos múltiples, simplemente modifiquemos el programa:

función MyFun: Integer var

i: Integer

para i := 0 a 500000

comenzar

Form1.Canvas.Lock;

Form1.Canvas.TextOut( 10, 10, IntToStr(i ));

Form1.Canvas.Unlock;

fin;

Resultado:= 0; fin;

procedimiento TForm1.Button1Click (Remitente: TObject); comenzar

MyFun; finalizar

Detalles de los cambios en el programa anterior:

1. -enhebrado todavía, y también hará que el formulario esté "muerto" por un tiempo;

2. El código de ejecución está escrito en una función, pero esta función no pertenece al método de TForm1, por lo que se usa. Canvas debe tener un nombre (Form1);

3. Dado que es una función, debe tener un valor de retorno (sea necesario o no);

4. se usaron 500001 veces.

Canvas.Lock es como decir: Canvas (superficie de dibujo) está ocupado, otros que quieran usar Canvas esperarán;

Canvas.Unlock: Agotado, ¡desbloquear!

Es un buen hábito usar Bloquear y Desbloquear en Canvas. No importa si no se utilizan subprocesos múltiples, pero no hay garantía de que el programa se expanda a uno de subprocesos múltiples. día; ahora estamos aprendiendo sobre subprocesos múltiples, así que por supuesto deberíamos usarlo.

Hay dos formas de usar subprocesos múltiples en Delphi: llamar a la API y usar la clase TThread; La API es más sencilla.

función MyFun(p:

Puntero): Entero; stdcall; var

i: Entero; comenzar

para i:= 0 a 500000

comenzar

Form1.Canvas.Lock;

Form1.Canvas.TextOut(10, 10, IntToStr(i));

Form1.Canvas.Unlock;

fin ;

Resultado:= 0; fin;

procedimiento TForm1.Button1Click(Remitente: TObject

ID: THandle; p>CreateThread(nil, 0, @MyFun, nil, 0, ID);

Análisis de código:

Después de crear un hilo, cuente el hilo principal original, por lo que El programa tiene dos subprocesos y es un subproceso múltiple estándar;

El tercer parámetro de CreateThread es el puntero de función. La función se ejecutará inmediatamente después de que se establezca el nuevo subproceso. destruirá el hilo, poniendo fin a la historia del subproceso múltiple.

La función que utilizará CreateThread es a nivel de sistema, no puede ser un método de una determinada clase (por ejemplo: TForm1) y es estricta. requisitos de formato (parámetros, valores de retorno), sin importar si lo necesita o no, debe seguir el formato;

Debido a que es una llamada a nivel de sistema, se le deben agregar las coordenadas stdcall. el orden de los parámetros. Aunque aquí solo hay un parámetro y no hay orden, esta es la convención de uso de funciones del sistema.

CreateThread también necesita un parámetro var para aceptar el ID del nuevo hilo. Aunque no se usa por el momento, este también es el formato; hablaremos de otros parámetros más adelante.

De esta manera El programa multiproceso más simple está disponible, implementémoslo nuevamente usando la clase TThread.

tipo

TMyThread = clase(TThread)

protegido

procedimiento Ejecutar; anular;

fin;

procedimiento TMyThread.Execute; var

i: Integer; comenzar

FreeOnTerminate := True; esto permite que el hilo se libere inmediatamente después de la ejecución}

para i:= 0 a 500000

comenzar

Form1.Canvas. Lock;

Form1.Canvas.TextOut(10, 10, IntToStr(i));

Form1.Canvas.Unlock;

fin; fin;

procedimiento TForm1.Button1Click(Remitente: TObject);

TMyThread.Create(False); end;

La clase TThread tiene un método abstracto (Execute), por lo que es una clase abstracta que solo se puede heredar y utilizar. Lo anterior se hereda como TMyThread.

Heredar TThread implementa principalmente el método abstracto Ejecutar (escriba nuestro código en él) y espera a que se cree una instancia de nuestro TMyThread, y se ejecutará el código en el método Execute. primero.